mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 08:07:19 -06:00
21.02
This commit is contained in:
@@ -67,8 +67,11 @@ bool CDoubleZeroStringListW::Add(LPCWSTR s) throw()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define MY__OFN_PROJECT 0x00400000
|
||||
#define MY__OFN_SHOW_ALL 0x01000000
|
||||
#endif
|
||||
|
||||
/* if (lpstrFilter == NULL && nFilterIndex == 0)
|
||||
MSDN : "the system doesn't show any files",
|
||||
@@ -91,14 +94,34 @@ So we use size of old version of structure. */
|
||||
|
||||
#if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500)
|
||||
// || !defined(WINVER)
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA)
|
||||
#endif
|
||||
#define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW)
|
||||
#else
|
||||
|
||||
// MinGW doesn't support some required macros. So we define them here:
|
||||
#ifndef CDSIZEOF_STRUCT
|
||||
#define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
|
||||
#endif
|
||||
#ifndef _UNICODE
|
||||
#ifndef OPENFILENAME_SIZE_VERSION_400A
|
||||
#define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef OPENFILENAME_SIZE_VERSION_400W
|
||||
#define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A
|
||||
#endif
|
||||
#define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; }
|
||||
#endif
|
||||
|
||||
bool MyGetOpenFileName(HWND hwnd, LPCWSTR title,
|
||||
LPCWSTR initialDir,
|
||||
|
||||
@@ -43,10 +43,10 @@ LRESULT CComboBox::GetLBText(int index, UString &s)
|
||||
s.Empty();
|
||||
if (g_IsNT)
|
||||
{
|
||||
LRESULT len = SendMsgW(CB_GETLBTEXTLEN, index, 0);
|
||||
LRESULT len = SendMsgW(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0);
|
||||
if (len == CB_ERR)
|
||||
return len;
|
||||
LRESULT len2 = SendMsgW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len));
|
||||
LRESULT len2 = SendMsgW(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s.GetBuf((unsigned)len));
|
||||
if (len2 == CB_ERR)
|
||||
return len;
|
||||
if (len > len2)
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <CommCtrl.h>
|
||||
|
||||
#include "../Window.h"
|
||||
|
||||
namespace NWindows {
|
||||
namespace NControl {
|
||||
|
||||
#define MY__int_TO_WPARAM(i) ((WPARAM)(INT_PTR)(i))
|
||||
|
||||
class CComboBox: public CWindow
|
||||
{
|
||||
public:
|
||||
@@ -20,19 +22,25 @@ public:
|
||||
#ifndef _UNICODE
|
||||
LRESULT AddString(LPCWSTR s);
|
||||
#endif
|
||||
LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, index, 0); }
|
||||
|
||||
/* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/
|
||||
LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY__int_TO_WPARAM(index), 0); }
|
||||
|
||||
/* If no item is selected, it returns CB_ERR (-1) */
|
||||
int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); }
|
||||
|
||||
/* If an error occurs, it is CB_ERR (-1) */
|
||||
int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); }
|
||||
|
||||
LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, index, 0); }
|
||||
LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, index, (LPARAM)s); }
|
||||
LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0); }
|
||||
LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s); }
|
||||
LRESULT GetLBText(int index, CSysString &s);
|
||||
#ifndef _UNICODE
|
||||
LRESULT GetLBText(int index, UString &s);
|
||||
#endif
|
||||
|
||||
LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, index, lParam); }
|
||||
LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, index, 0); }
|
||||
LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, MY__int_TO_WPARAM(index), lParam); }
|
||||
LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, MY__int_TO_WPARAM(index), 0); }
|
||||
|
||||
LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); }
|
||||
|
||||
@@ -46,7 +54,11 @@ class CComboBoxEx: public CComboBox
|
||||
public:
|
||||
bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); }
|
||||
|
||||
LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, index, 0); }
|
||||
/* Returns:
|
||||
an INT value that represents the number of items remaining in the control.
|
||||
If (index) is invalid, the message returns CB_ERR. */
|
||||
LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, MY__int_TO_WPARAM(index), 0); }
|
||||
|
||||
LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); }
|
||||
#ifndef _UNICODE
|
||||
LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifndef __WINDOWS_CONTROL_IMAGE_LIST_H
|
||||
#define __WINDOWS_CONTROL_IMAGE_LIST_H
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <CommCtrl.h>
|
||||
|
||||
#include "../Defs.h"
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width)
|
||||
{
|
||||
LVCOLUMN ci;
|
||||
ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
||||
ci.pszText = (LPTSTR)text;
|
||||
ci.pszText = (LPTSTR)(void *)text;
|
||||
ci.iSubItem = columnIndex;
|
||||
ci.cx = width;
|
||||
return InsertColumn(columnIndex, &ci);
|
||||
@@ -47,7 +47,7 @@ int CListView::InsertItem(int index, LPCTSTR text)
|
||||
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
item.iItem = index;
|
||||
item.lParam = index;
|
||||
item.pszText = (LPTSTR)text;
|
||||
item.pszText = (LPTSTR)(void *)text;
|
||||
item.iSubItem = 0;
|
||||
return InsertItem(&item);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ int CListView::SetSubItem(int index, int subIndex, LPCTSTR text)
|
||||
LVITEM item;
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = index;
|
||||
item.pszText = (LPTSTR)text;
|
||||
item.pszText = (LPTSTR)(void *)text;
|
||||
item.iSubItem = subIndex;
|
||||
return SetItem(&item);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width)
|
||||
{
|
||||
LVCOLUMNW ci;
|
||||
ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
||||
ci.pszText = (LPWSTR)text;
|
||||
ci.pszText = (LPWSTR)(void *)text;
|
||||
ci.iSubItem = columnIndex;
|
||||
ci.cx = width;
|
||||
return InsertColumn(columnIndex, &ci);
|
||||
@@ -80,7 +80,7 @@ int CListView::InsertItem(int index, LPCWSTR text)
|
||||
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
item.iItem = index;
|
||||
item.lParam = index;
|
||||
item.pszText = (LPWSTR)text;
|
||||
item.pszText = (LPWSTR)(void *)text;
|
||||
item.iSubItem = 0;
|
||||
return InsertItem(&item);
|
||||
}
|
||||
@@ -90,7 +90,7 @@ int CListView::SetSubItem(int index, int subIndex, LPCWSTR text)
|
||||
LVITEMW item;
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = index;
|
||||
item.pszText = (LPWSTR)text;
|
||||
item.pszText = (LPWSTR)(void *)text;
|
||||
item.iSubItem = subIndex;
|
||||
return SetItem(&item);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <CommCtrl.h>
|
||||
|
||||
#include "../Window.h"
|
||||
|
||||
@@ -32,7 +32,8 @@ public:
|
||||
|
||||
int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); }
|
||||
int InsertColumn(int columnIndex, LPCTSTR text, int width);
|
||||
bool SetColumnOrderArray(int count, const int *columns) { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, columns)); }
|
||||
bool SetColumnOrderArray(int count, const int *columns)
|
||||
{ return BOOLToBool(ListView_SetColumnOrderArray(_window, count, (int *)(void *)columns)); }
|
||||
|
||||
/*
|
||||
int GetNumColumns()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <CommCtrl.h>
|
||||
|
||||
#include "../Window.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include <prsht.h>
|
||||
#include <PrSht.h>
|
||||
|
||||
#include "Dialog.h"
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "DLL.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef _UNICODE
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
@@ -97,7 +99,7 @@ FString GetModuleDirPrefix()
|
||||
{
|
||||
int pos = s.ReverseFind_PathSepar();
|
||||
if (pos >= 0)
|
||||
s.DeleteFrom(pos + 1);
|
||||
s.DeleteFrom((unsigned)(pos + 1));
|
||||
}
|
||||
if (s.IsEmpty())
|
||||
s = "." STRING_PATH_SEPARATOR;
|
||||
@@ -107,3 +109,83 @@ FString GetModuleDirPrefix()
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#else
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace NWindows {
|
||||
namespace NDLL {
|
||||
|
||||
bool CLibrary::Free() throw()
|
||||
{
|
||||
if (_module == NULL)
|
||||
return true;
|
||||
int ret = dlclose(_module);
|
||||
if (ret != 0)
|
||||
return false;
|
||||
_module = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
// FARPROC
|
||||
void *
|
||||
local_GetProcAddress(HMODULE module, LPCSTR procName)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
if (module)
|
||||
{
|
||||
ptr = dlsym(module, procName);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool CLibrary::Load(CFSTR path) throw()
|
||||
{
|
||||
if (!Free())
|
||||
return false;
|
||||
|
||||
int options = 0;
|
||||
|
||||
#ifdef RTLD_LOCAL
|
||||
options |= RTLD_LOCAL;
|
||||
#endif
|
||||
|
||||
#ifdef RTLD_NOW
|
||||
options |= RTLD_NOW;
|
||||
#endif
|
||||
|
||||
#ifdef RTLD_GROUP
|
||||
#if ! (defined(hpux) || defined(__hpux))
|
||||
options |= RTLD_GROUP; // mainly for solaris but not for HPUX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void *handler = dlopen(path, options);
|
||||
|
||||
if (handler)
|
||||
{
|
||||
// here we can transfer some settings to DLL
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
_module = handler;
|
||||
|
||||
return (_module != NULL);
|
||||
}
|
||||
|
||||
// FARPROC
|
||||
void * CLibrary::GetProc(LPCSTR procName) const
|
||||
{
|
||||
// return My_GetProcAddress(_module, procName);
|
||||
return local_GetProcAddress(_module, procName);
|
||||
// return NULL;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
namespace NWindows {
|
||||
namespace NDLL {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName)
|
||||
#define My_GetProcAddress(module, procName) (void *)::GetProcAddressA(module, procName)
|
||||
#else
|
||||
#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName)
|
||||
#define My_GetProcAddress(module, procName) (void *)::GetProcAddress(module, procName)
|
||||
#endif
|
||||
|
||||
/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another
|
||||
@@ -46,9 +48,33 @@ public:
|
||||
bool Free() throw();
|
||||
bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw();
|
||||
bool Load(CFSTR path) throw();
|
||||
FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }
|
||||
// FARPROC
|
||||
void *GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
typedef void * HMODULE;
|
||||
// typedef int (*FARPROC)();
|
||||
// typedef void *FARPROC;
|
||||
|
||||
class CLibrary
|
||||
{
|
||||
HMODULE _module;
|
||||
|
||||
// CLASS_NO_COPY(CLibrary);
|
||||
public:
|
||||
CLibrary(): _module(NULL) {};
|
||||
~CLibrary() { Free(); }
|
||||
|
||||
bool Free() throw();
|
||||
bool Load(CFSTR path) throw();
|
||||
// FARPROC
|
||||
void *GetProc(LPCSTR procName) const; // { return My_GetProcAddress(_module, procName); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
bool MyGetModuleFileName(FString &path);
|
||||
|
||||
FString GetModuleDirPrefix();
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); }
|
||||
inline bool BOOLToBool(BOOL v) { return (v != FALSE); }
|
||||
inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); }
|
||||
#endif
|
||||
|
||||
inline bool BOOLToBool(BOOL v) { return (v != FALSE); }
|
||||
|
||||
inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); }
|
||||
inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); }
|
||||
|
||||
|
||||
@@ -2,21 +2,25 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
#if !defined(_UNICODE) || !defined(_WIN32)
|
||||
#include "../Common/StringConvert.h"
|
||||
#endif
|
||||
|
||||
#include "ErrorMsg.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
#ifdef _WIN32
|
||||
#if !defined(_UNICODE)
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace NWindows {
|
||||
namespace NError {
|
||||
|
||||
static bool MyFormatMessage(DWORD errorCode, UString &message)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
LPVOID msgBuf;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -38,8 +42,63 @@ static bool MyFormatMessage(DWORD errorCode, UString &message)
|
||||
}
|
||||
::LocalFree(msgBuf);
|
||||
return true;
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
AString m;
|
||||
|
||||
const char *s = NULL;
|
||||
|
||||
switch ((Int32)errorCode)
|
||||
{
|
||||
// case ERROR_NO_MORE_FILES : s = "No more files"; break;
|
||||
// case ERROR_DIRECTORY : s = "Error Directory"; break;
|
||||
case E_NOTIMPL : s = "E_NOTIMPL : Not implemented"; break;
|
||||
case E_NOINTERFACE : s = "E_NOINTERFACE : No such interface supported"; break;
|
||||
case E_ABORT : s = "E_ABORT : Operation aborted"; break;
|
||||
case E_FAIL : s = "E_FAIL : Unspecified error"; break;
|
||||
|
||||
case STG_E_INVALIDFUNCTION : s = "STG_E_INVALIDFUNCTION"; break;
|
||||
case CLASS_E_CLASSNOTAVAILABLE : s = "CLASS_E_CLASSNOTAVAILABLE"; break;
|
||||
|
||||
case E_OUTOFMEMORY : s = "E_OUTOFMEMORY : Can't allocate required memory"; break;
|
||||
case E_INVALIDARG : s = "E_INVALIDARG : One or more arguments are invalid"; break;
|
||||
|
||||
// case MY__E_ERROR_NEGATIVE_SEEK : s = "MY__E_ERROR_NEGATIVE_SEEK"; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* strerror() for unknow errors still shows message "Unknown error -12345678")
|
||||
So we must trasfer error codes before strerror() */
|
||||
if (!s)
|
||||
{
|
||||
if ((errorCode & 0xFFFF0000) == (UInt32)((MY__FACILITY__WRes << 16) | 0x80000000))
|
||||
errorCode &= 0xFFFF;
|
||||
else if ((errorCode & ((UInt32)1 << 31)))
|
||||
return false; // we will show hex error later for that case
|
||||
|
||||
s = strerror((int)errorCode);
|
||||
|
||||
// if (!s)
|
||||
{
|
||||
m += "errno=";
|
||||
m.Add_UInt32(errorCode);
|
||||
if (s)
|
||||
m += " : ";
|
||||
}
|
||||
}
|
||||
|
||||
if (s)
|
||||
m += s;
|
||||
|
||||
MultiByteToUnicodeString2(message, m);
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
UString MyFormatMessage(DWORD errorCode)
|
||||
{
|
||||
UString m;
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace NWindows {
|
||||
namespace NError {
|
||||
|
||||
UString MyFormatMessage(DWORD errorCode);
|
||||
inline UString MyFormatMessage(HRESULT errorCode) { return MyFormatMessage((DWORD)errorCode); }
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -2,8 +2,21 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <utime.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../Common/StringConvert.h"
|
||||
#include "../Common/C_FileIO.h"
|
||||
#include "TimeUtils.h"
|
||||
#endif
|
||||
|
||||
#include "FileDir.h"
|
||||
@@ -22,6 +35,8 @@ namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NDir {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
bool GetWindowsDir(FString &path)
|
||||
@@ -67,7 +82,8 @@ bool GetSystemDir(FString &path)
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
}
|
||||
#endif
|
||||
#endif // UNDER_CE
|
||||
|
||||
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
{
|
||||
@@ -102,6 +118,8 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
@@ -131,8 +149,10 @@ bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||
|
||||
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if ((attrib & 0xF0000000) != 0)
|
||||
attrib &= 0x3FFF;
|
||||
#endif
|
||||
return SetFileAttrib(path, attrib);
|
||||
}
|
||||
|
||||
@@ -163,6 +183,7 @@ bool RemoveDir(CFSTR path)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
@@ -175,8 +196,10 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
#endif
|
||||
{
|
||||
IF_USE_MAIN_PATH_2(oldFile, newFile)
|
||||
{
|
||||
if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))
|
||||
return true;
|
||||
}
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH_2)
|
||||
{
|
||||
@@ -190,7 +213,6 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
typedef BOOL (WINAPI *Func_CreateHardLinkW)(
|
||||
LPCWSTR lpFileName,
|
||||
@@ -198,6 +220,7 @@ typedef BOOL (WINAPI *Func_CreateHardLinkW)(
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
||||
);
|
||||
EXTERN_C_END
|
||||
#endif // UNDER_CE
|
||||
|
||||
bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
{
|
||||
@@ -215,12 +238,14 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
#endif
|
||||
{
|
||||
Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW)
|
||||
::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW");
|
||||
(void *)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW");
|
||||
if (!my_CreateHardLinkW)
|
||||
return false;
|
||||
IF_USE_MAIN_PATH_2(newFileName, existFileName)
|
||||
{
|
||||
if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))
|
||||
return true;
|
||||
}
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH_2)
|
||||
{
|
||||
@@ -233,7 +258,6 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
WinXP-64 CreateDir():
|
||||
@@ -333,6 +357,10 @@ static bool CreateDir2(CFSTR path)
|
||||
return fi.IsDir();
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
static bool CreateDir2(CFSTR path);
|
||||
|
||||
bool CreateComplexDir(CFSTR _path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -348,11 +376,21 @@ bool CreateComplexDir(CFSTR _path)
|
||||
if (IsDriveRootPath_SuperAllowed(_path))
|
||||
return false;
|
||||
|
||||
unsigned prefixSize = GetRootPrefixSize(_path);
|
||||
const unsigned prefixSize = GetRootPrefixSize(_path);
|
||||
|
||||
#endif
|
||||
#endif // UNDER_CE
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// Posix
|
||||
NFind::CFileInfo fi;
|
||||
if (fi.Find(_path))
|
||||
{
|
||||
if (fi.IsDir())
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
|
||||
FString path (_path);
|
||||
|
||||
@@ -365,7 +403,7 @@ bool CreateComplexDir(CFSTR _path)
|
||||
}
|
||||
|
||||
const FString path2 (path);
|
||||
pos = path.Len();
|
||||
pos = (int)path.Len();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -384,17 +422,17 @@ bool CreateComplexDir(CFSTR _path)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
path.DeleteFrom(pos);
|
||||
path.DeleteFrom((unsigned)pos);
|
||||
}
|
||||
|
||||
while (pos < (int)path2.Len())
|
||||
{
|
||||
int pos2 = NName::FindSepar(path2.Ptr(pos + 1));
|
||||
int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1));
|
||||
if (pos2 < 0)
|
||||
pos = path2.Len();
|
||||
pos = (int)path2.Len();
|
||||
else
|
||||
pos += 1 + pos2;
|
||||
path.SetFrom(path2, pos);
|
||||
path.SetFrom(path2, (unsigned)pos);
|
||||
if (!CreateDir(path))
|
||||
return false;
|
||||
}
|
||||
@@ -402,6 +440,9 @@ bool CreateComplexDir(CFSTR _path)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool DeleteFileAlways(CFSTR path)
|
||||
{
|
||||
/* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.
|
||||
@@ -412,7 +453,7 @@ bool DeleteFileAlways(CFSTR path)
|
||||
&& (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0
|
||||
&& (attrib & FILE_ATTRIBUTE_READONLY) != 0)
|
||||
{
|
||||
if (!SetFileAttrib(path, attrib & ~FILE_ATTRIBUTE_READONLY))
|
||||
if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -443,6 +484,8 @@ bool DeleteFileAlways(CFSTR path)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RemoveDirWithSubItems(const FString &path)
|
||||
{
|
||||
bool needRemoveSubItems = true;
|
||||
@@ -466,7 +509,9 @@ bool RemoveDirWithSubItems(const FString &path)
|
||||
const unsigned prefixSize = s.Len();
|
||||
NFind::CEnumerator enumerator;
|
||||
enumerator.SetDirPrefix(s);
|
||||
NFind::CFileInfo fi;
|
||||
NFind::CDirEntry fi;
|
||||
bool isError = false;
|
||||
DWORD lastError = 0;
|
||||
while (enumerator.Next(fi))
|
||||
{
|
||||
s.DeleteFrom(prefixSize);
|
||||
@@ -474,18 +519,32 @@ bool RemoveDirWithSubItems(const FString &path)
|
||||
if (fi.IsDir())
|
||||
{
|
||||
if (!RemoveDirWithSubItems(s))
|
||||
return false;
|
||||
{
|
||||
lastError = GetLastError();
|
||||
isError = true;
|
||||
}
|
||||
}
|
||||
else if (!DeleteFileAlways(s))
|
||||
return false;
|
||||
{
|
||||
lastError = GetLastError();
|
||||
isError = false;
|
||||
}
|
||||
}
|
||||
if (isError)
|
||||
{
|
||||
SetLastError(lastError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we clear read-only attrib to remove read-only dir
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
return RemoveDir(path);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
bool MyGetFullPathName(CFSTR path, FString &resFullPath)
|
||||
@@ -501,6 +560,8 @@ bool MyGetFullPathName(CFSTR path, FString &resFullPath)
|
||||
return GetFullPath(path, resFullPath);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool SetCurrentDir(CFSTR path)
|
||||
{
|
||||
// SetCurrentDirectory doesn't support \\?\ prefix
|
||||
@@ -516,9 +577,11 @@ bool SetCurrentDir(CFSTR path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool GetCurrentDir(FString &path)
|
||||
{
|
||||
path.Empty();
|
||||
|
||||
DWORD needLength;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -539,7 +602,9 @@ bool GetCurrentDir(FString &path)
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
#endif // UNDER_CE
|
||||
|
||||
|
||||
bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)
|
||||
{
|
||||
@@ -547,8 +612,9 @@ bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName
|
||||
if (!res)
|
||||
resDirPrefix = path;
|
||||
int pos = resDirPrefix.ReverseFind_PathSepar();
|
||||
resFileName = resDirPrefix.Ptr(pos + 1);
|
||||
resDirPrefix.DeleteFrom(pos + 1);
|
||||
pos++;
|
||||
resFileName = resDirPrefix.Ptr((unsigned)pos);
|
||||
resDirPrefix.DeleteFrom((unsigned)pos);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -560,6 +626,7 @@ bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)
|
||||
|
||||
bool MyGetTempPath(FString &path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
path.Empty();
|
||||
DWORD needLength;
|
||||
#ifndef _UNICODE
|
||||
@@ -579,11 +646,27 @@ bool MyGetTempPath(FString &path)
|
||||
path = us2fs(s);
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
|
||||
#else
|
||||
|
||||
// FIXME: improve that code
|
||||
path = "/tmp/";
|
||||
if (!NFind::DoesDirExist_FollowLink(path))
|
||||
path = "./";
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile)
|
||||
{
|
||||
UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
|
||||
UInt32 d =
|
||||
#ifdef _WIN32
|
||||
(GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
|
||||
#else
|
||||
(UInt32)(time(NULL) << 12) ^ ((UInt32)getppid() << 14) ^ (UInt32)(getpid());
|
||||
#endif
|
||||
|
||||
for (unsigned i = 0; i < 100; i++)
|
||||
{
|
||||
path = prefix;
|
||||
@@ -670,7 +753,7 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
|
||||
// DWORD attrib = 0;
|
||||
if (deleteDestBefore)
|
||||
{
|
||||
if (NFind::DoesFileExist(name))
|
||||
if (NFind::DoesFileExist_Raw(name))
|
||||
{
|
||||
// attrib = NFind::GetFileAttrib(name);
|
||||
if (!DeleteFileAlways(name))
|
||||
@@ -690,6 +773,7 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
bool CTempDir::Create(CFSTR prefix)
|
||||
{
|
||||
if (!Remove())
|
||||
@@ -710,5 +794,285 @@ bool CTempDir::Remove()
|
||||
_mustBeDeleted = !RemoveDirWithSubItems(_path);
|
||||
return !_mustBeDeleted;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
bool RemoveDir(CFSTR path)
|
||||
{
|
||||
return (rmdir(path) == 0);
|
||||
}
|
||||
|
||||
|
||||
static BOOL My__CopyFile(CFSTR oldFile, CFSTR newFile)
|
||||
{
|
||||
NWindows::NFile::NIO::COutFile outFile;
|
||||
if (!outFile.Create(newFile, false))
|
||||
return FALSE;
|
||||
|
||||
NWindows::NFile::NIO::CInFile inFile;
|
||||
if (!inFile.Open(oldFile))
|
||||
return FALSE;
|
||||
|
||||
char buf[1 << 14];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const ssize_t num = inFile.read_part(buf, sizeof(buf));
|
||||
if (num == 0)
|
||||
return TRUE;
|
||||
if (num < 0)
|
||||
return FALSE;
|
||||
size_t processed;
|
||||
const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);
|
||||
if (num2 != num || processed != (size_t)num)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
{
|
||||
int res = rename(oldFile, newFile);
|
||||
if (res == 0)
|
||||
return true;
|
||||
if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)
|
||||
return false;
|
||||
|
||||
if (My__CopyFile(oldFile, newFile) == FALSE)
|
||||
return false;
|
||||
|
||||
struct stat info_file;
|
||||
res = stat(oldFile, &info_file);
|
||||
if (res != 0)
|
||||
return false;
|
||||
|
||||
/*
|
||||
ret = chmod(dst,info_file.st_mode & g_umask.mask);
|
||||
*/
|
||||
return (unlink(oldFile) == 0);
|
||||
}
|
||||
|
||||
|
||||
bool CreateDir(CFSTR path)
|
||||
{
|
||||
return (mkdir(path, 0777) == 0); // change it
|
||||
}
|
||||
|
||||
static bool CreateDir2(CFSTR path)
|
||||
{
|
||||
return (mkdir(path, 0777) == 0); // change it
|
||||
}
|
||||
|
||||
|
||||
bool DeleteFileAlways(CFSTR path)
|
||||
{
|
||||
return (remove(path) == 0);
|
||||
}
|
||||
|
||||
bool SetCurrentDir(CFSTR path)
|
||||
{
|
||||
return (chdir(path) == 0);
|
||||
}
|
||||
|
||||
|
||||
bool GetCurrentDir(FString &path)
|
||||
{
|
||||
path.Empty();
|
||||
|
||||
#define MY__PATH_MAX PATH_MAX
|
||||
// #define MY__PATH_MAX 1024
|
||||
|
||||
char s[MY__PATH_MAX + 1];
|
||||
char *res = getcwd(s, MY__PATH_MAX);
|
||||
if (!res)
|
||||
{
|
||||
// if (errno != ERANGE)
|
||||
return false;
|
||||
}
|
||||
path = fas2fs(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void FILETME_To_timespec(const FILETIME *ft, timespec &ts)
|
||||
{
|
||||
if (ft)
|
||||
{
|
||||
const Int64 sec = NTime::FileTimeToUnixTime64(*ft);
|
||||
// time_t is long
|
||||
const time_t sec2 = (time_t)sec;
|
||||
if (sec2 == sec)
|
||||
{
|
||||
ts.tv_sec = sec2;
|
||||
const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
|
||||
ts.tv_nsec = (long)((winTime % 10000000) * 100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// else
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
// ts.tv_nsec = UTIME_NOW; // set to the current time
|
||||
ts.tv_nsec = UTIME_OMIT; // keep old timesptamp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
{
|
||||
// need testing
|
||||
/*
|
||||
struct utimbuf buf;
|
||||
struct stat st;
|
||||
UNUSED_VAR(cTime)
|
||||
|
||||
printf("\nstat = %s\n", path);
|
||||
int ret = stat(path, &st);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
buf.actime = st.st_atime;
|
||||
buf.modtime = st.st_mtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t cur_time = time(0);
|
||||
buf.actime = cur_time;
|
||||
buf.modtime = cur_time;
|
||||
}
|
||||
|
||||
if (aTime)
|
||||
{
|
||||
UInt32 ut;
|
||||
if (NTime::FileTimeToUnixTime(*aTime, ut))
|
||||
buf.actime = ut;
|
||||
}
|
||||
|
||||
if (mTime)
|
||||
{
|
||||
UInt32 ut;
|
||||
if (NTime::FileTimeToUnixTime(*mTime, ut))
|
||||
buf.modtime = ut;
|
||||
}
|
||||
|
||||
return utime(path, &buf) == 0;
|
||||
*/
|
||||
|
||||
// if (!aTime && !mTime) return true;
|
||||
|
||||
struct timespec times[2];
|
||||
UNUSED_VAR(cTime)
|
||||
|
||||
FILETME_To_timespec(aTime, times[0]);
|
||||
FILETME_To_timespec(mTime, times[1]);
|
||||
|
||||
const int flags = 0; // follow link
|
||||
// = AT_SYMLINK_NOFOLLOW; // don't follow link
|
||||
return utimensat(AT_FDCWD, path, times, flags) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct C_umask
|
||||
{
|
||||
mode_t mask;
|
||||
|
||||
C_umask()
|
||||
{
|
||||
/* by security reasons we restrict attributes according
|
||||
with process's file mode creation mask (umask) */
|
||||
const mode_t um = umask(0); // octal :0022 is expected
|
||||
mask = 0777 & (~um); // octal: 0755 is expected
|
||||
umask(um); // restore the umask
|
||||
// printf("\n umask = 0%03o mask = 0%03o\n", um, mask);
|
||||
|
||||
// mask = 0777; // debug we can disable the restriction:
|
||||
}
|
||||
};
|
||||
|
||||
static C_umask g_umask;
|
||||
|
||||
// #define PRF(x) x;
|
||||
#define PRF(x)
|
||||
|
||||
#define TRACE_SetFileAttrib(msg) \
|
||||
PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg));
|
||||
|
||||
#define TRACE_chmod(s, mode) \
|
||||
PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode)));
|
||||
|
||||
|
||||
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
{
|
||||
TRACE_SetFileAttrib("");
|
||||
|
||||
struct stat st;
|
||||
|
||||
bool use_lstat = true;
|
||||
if (use_lstat)
|
||||
{
|
||||
if (lstat(path, &st) != 0)
|
||||
{
|
||||
TRACE_SetFileAttrib("bad lstat()");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
TRACE_SetFileAttrib("bad stat()");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
|
||||
{
|
||||
st.st_mode = attrib >> 16;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
// user/7z must be able to create files in this directory
|
||||
st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR);
|
||||
}
|
||||
else if (!S_ISREG(st.st_mode))
|
||||
return true;
|
||||
}
|
||||
else if (S_ISLNK(st.st_mode))
|
||||
{
|
||||
// change it
|
||||
SetLastError(ENOSYS);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only Windows Attributes
|
||||
if (S_ISDIR(st.st_mode)
|
||||
|| (attrib & FILE_ATTRIBUTE_READONLY) == 0)
|
||||
return true;
|
||||
st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions
|
||||
}
|
||||
|
||||
TRACE_chmod(path, (st.st_mode) & g_umask.mask);
|
||||
int res = chmod(path, (st.st_mode) & g_umask.mask);
|
||||
|
||||
// TRACE_SetFileAttrib("OK")
|
||||
return (res == 0);
|
||||
}
|
||||
|
||||
|
||||
bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
{
|
||||
PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName));
|
||||
return (link(existFileName, newFileName) == 0);
|
||||
}
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
// #endif
|
||||
|
||||
}}}
|
||||
|
||||
@@ -17,6 +17,8 @@ bool GetSystemDir(FString &path);
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool SetFileAttrib(CFSTR path, DWORD attrib);
|
||||
|
||||
/*
|
||||
@@ -26,6 +28,8 @@ bool SetFileAttrib(CFSTR path, DWORD attrib);
|
||||
bits that are related to current system only.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib);
|
||||
|
||||
|
||||
@@ -61,7 +65,7 @@ bool GetCurrentDir(FString &resultPath);
|
||||
|
||||
bool MyGetTempPath(FString &resultPath);
|
||||
|
||||
class CTempFile
|
||||
class CTempFile MY_UNCOPYABLE
|
||||
{
|
||||
bool _mustBeDeleted;
|
||||
FString _path;
|
||||
@@ -76,7 +80,9 @@ public:
|
||||
bool MoveTo(CFSTR name, bool deleteDestBefore);
|
||||
};
|
||||
|
||||
class CTempDir
|
||||
|
||||
#ifdef _WIN32
|
||||
class CTempDir MY_UNCOPYABLE
|
||||
{
|
||||
bool _mustBeDeleted;
|
||||
FString _path;
|
||||
@@ -88,9 +94,11 @@ public:
|
||||
bool Create(CFSTR namePrefix) ;
|
||||
bool Remove();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(UNDER_CE)
|
||||
class CCurrentDirRestorer
|
||||
class CCurrentDirRestorer MY_UNCOPYABLE
|
||||
{
|
||||
FString _path;
|
||||
public:
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
#include "../Common/StringConvert.h"
|
||||
// #include <stdio.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fcntl.h> /* Definition of AT_* constants */
|
||||
#include "TimeUtils.h"
|
||||
#endif
|
||||
|
||||
#include "FileFind.h"
|
||||
@@ -34,27 +37,51 @@ typedef struct
|
||||
WCHAR cStreamName[MAX_PATH + 36];
|
||||
} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA;
|
||||
|
||||
typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel,
|
||||
typedef HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel,
|
||||
LPVOID findStreamData, DWORD flags);
|
||||
|
||||
typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData);
|
||||
typedef BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
#endif // defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
namespace NSystem
|
||||
{
|
||||
bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace NFind {
|
||||
|
||||
#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
|
||||
|
||||
void CFileInfoBase::ClearBase() throw()
|
||||
{
|
||||
Size = 0;
|
||||
MY_CLEAR_FILETIME(CTime);
|
||||
MY_CLEAR_FILETIME(ATime);
|
||||
MY_CLEAR_FILETIME(MTime);
|
||||
Attrib = 0;
|
||||
// ReparseTag = 0;
|
||||
IsAltStream = false;
|
||||
IsDevice = false;
|
||||
|
||||
#ifndef _WIN32
|
||||
ino = 0;
|
||||
nlink = 0;
|
||||
mode = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CFileInfo::IsDots() const throw()
|
||||
{
|
||||
if (!IsDir() || Name.IsEmpty())
|
||||
@@ -64,12 +91,17 @@ bool CFileInfo::IsDots() const throw()
|
||||
return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#define WIN_FD_TO_MY_FI(fi, fd) \
|
||||
fi.Attrib = fd.dwFileAttributes; \
|
||||
fi.CTime = fd.ftCreationTime; \
|
||||
fi.ATime = fd.ftLastAccessTime; \
|
||||
fi.MTime = fd.ftLastWriteTime; \
|
||||
fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \
|
||||
/* fi.ReparseTag = fd.dwReserved0; */ \
|
||||
fi.IsAltStream = false; \
|
||||
fi.IsDevice = false;
|
||||
|
||||
@@ -91,7 +123,6 @@ static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFil
|
||||
}
|
||||
|
||||
#ifndef _UNICODE
|
||||
|
||||
static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)
|
||||
{
|
||||
WIN_FD_TO_MY_FI(fi, fd);
|
||||
@@ -143,7 +174,8 @@ WinXP-64 FindFirstFile():
|
||||
\\Server\Share_RootDrive - ERROR_INVALID_NAME
|
||||
\\Server\Share_RootDrive\ - ERROR_INVALID_NAME
|
||||
|
||||
c:\* - ERROR_FILE_NOT_FOUND, if thare are no item in that folder
|
||||
e:\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder
|
||||
w:\* - ERROR_PATH_NOT_FOUND, if there is no such drive w:
|
||||
*/
|
||||
|
||||
bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
|
||||
@@ -210,12 +242,13 @@ bool CFindFile::FindNext(CFileInfo &fi)
|
||||
static FindFirstStreamW_Ptr g_FindFirstStreamW;
|
||||
static FindNextStreamW_Ptr g_FindNextStreamW;
|
||||
|
||||
struct CFindStreamLoader
|
||||
static struct CFindStreamLoader
|
||||
{
|
||||
CFindStreamLoader()
|
||||
{
|
||||
g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW");
|
||||
g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW");
|
||||
HMODULE hm = ::GetModuleHandleA("kernel32.dll");
|
||||
g_FindFirstStreamW = (FindFirstStreamW_Ptr)(void *)::GetProcAddress(hm, "FindFirstStreamW");
|
||||
g_FindNextStreamW = (FindNextStreamW_Ptr)(void *)::GetProcAddress(hm, "FindNextStreamW");
|
||||
}
|
||||
} g_FindStreamLoader;
|
||||
|
||||
@@ -245,7 +278,7 @@ UString CStreamInfo::GetReducedName2() const
|
||||
|
||||
static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)
|
||||
{
|
||||
si.Size = sd.StreamSize.QuadPart;
|
||||
si.Size = (UInt64)sd.StreamSize.QuadPart;
|
||||
si.Name = sd.cStreamName;
|
||||
}
|
||||
|
||||
@@ -336,19 +369,6 @@ bool CStreamEnumerator::Next(CStreamInfo &si, bool &found)
|
||||
#endif
|
||||
|
||||
|
||||
#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
|
||||
|
||||
void CFileInfoBase::ClearBase() throw()
|
||||
{
|
||||
Size = 0;
|
||||
MY_CLEAR_FILETIME(CTime);
|
||||
MY_CLEAR_FILETIME(ATime);
|
||||
MY_CLEAR_FILETIME(MTime);
|
||||
Attrib = 0;
|
||||
IsAltStream = false;
|
||||
IsDevice = false;
|
||||
}
|
||||
|
||||
/*
|
||||
WinXP-64 GetFileAttributes():
|
||||
If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code
|
||||
@@ -416,7 +436,7 @@ also we support paths that are not supported by FindFirstFile:
|
||||
c::stream - Name = c::stream
|
||||
*/
|
||||
|
||||
bool CFileInfo::Find(CFSTR path)
|
||||
bool CFileInfo::Find(CFSTR path, bool followLink)
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (IsDevicePath(path))
|
||||
@@ -454,7 +474,7 @@ bool CFileInfo::Find(CFSTR path)
|
||||
{
|
||||
UString streamName = fs2us(path + (unsigned)colonPos);
|
||||
FString filePath (path);
|
||||
filePath.DeleteFrom(colonPos);
|
||||
filePath.DeleteFrom((unsigned)colonPos);
|
||||
/* we allow both cases:
|
||||
name:stream
|
||||
name:stream:$DATA
|
||||
@@ -467,7 +487,7 @@ bool CFileInfo::Find(CFSTR path)
|
||||
bool isOk = true;
|
||||
|
||||
if (IsDrivePath2(filePath) &&
|
||||
(colonPos == 2 || colonPos == 3 && filePath[2] == '\\'))
|
||||
(colonPos == 2 || (colonPos == 3 && filePath[2] == '\\')))
|
||||
{
|
||||
// FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT)
|
||||
ClearBase();
|
||||
@@ -476,11 +496,11 @@ bool CFileInfo::Find(CFSTR path)
|
||||
Name = filePath;
|
||||
}
|
||||
else
|
||||
isOk = Find(filePath);
|
||||
isOk = Find(filePath, followLink); // check it (followLink)
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
Attrib &= ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
Size = 0;
|
||||
CStreamEnumerator enumerator(filePath);
|
||||
for (;;)
|
||||
@@ -536,11 +556,15 @@ bool CFileInfo::Find(CFSTR path)
|
||||
ClearBase();
|
||||
Attrib = attrib;
|
||||
Name = path + rootSize;
|
||||
Name.DeleteFrom(2); // we don't need backslash (C:)
|
||||
Name.DeleteFrom(2);
|
||||
if (!Fill_From_ByHandleFileInfo(path))
|
||||
{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (IS_PATH_SEPAR(path[0]))
|
||||
{
|
||||
if (path[1] == 0)
|
||||
{
|
||||
DWORD attrib = GetFileAttrib(path);
|
||||
@@ -559,10 +583,15 @@ bool CFileInfo::Find(CFSTR path)
|
||||
{
|
||||
if (NName::FindSepar(path + prefixSize) < 0)
|
||||
{
|
||||
if (Fill_From_ByHandleFileInfo(path))
|
||||
{
|
||||
Name = path + prefixSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
FString s (path);
|
||||
s.Add_PathSepar();
|
||||
s += '*'; // CHAR_ANY_MASK
|
||||
|
||||
bool isOK = false;
|
||||
if (finder.FindFirst(s, *this))
|
||||
{
|
||||
@@ -577,7 +606,7 @@ bool CFileInfo::Find(CFSTR path)
|
||||
}
|
||||
{
|
||||
DWORD attrib = GetFileAttrib(path);
|
||||
if (isOK || attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0))
|
||||
{
|
||||
ClearBase();
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES)
|
||||
@@ -592,23 +621,105 @@ bool CFileInfo::Find(CFSTR path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return finder.FindFirst(path, *this);
|
||||
bool res = finder.FindFirst(path, *this);
|
||||
if (!followLink
|
||||
|| !res
|
||||
|| !HasReparsePoint())
|
||||
return res;
|
||||
|
||||
// return FollowReparse(path, IsDir());
|
||||
return Fill_From_ByHandleFileInfo(path);
|
||||
}
|
||||
|
||||
bool CFileInfo::Fill_From_ByHandleFileInfo(CFSTR path)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (!NIO::CFileBase::GetFileInformation(path, &info))
|
||||
return false;
|
||||
{
|
||||
Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
|
||||
CTime = info.ftCreationTime;
|
||||
ATime = info.ftLastAccessTime;
|
||||
MTime = info.ftLastWriteTime;
|
||||
Attrib = info.dwFileAttributes;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool DoesFileExist(CFSTR name)
|
||||
/*
|
||||
bool CFileInfo::FollowReparse(CFSTR path, bool isDir)
|
||||
{
|
||||
if (isDir)
|
||||
{
|
||||
FString prefix = path;
|
||||
prefix.Add_PathSepar();
|
||||
|
||||
// "folder/." refers to folder itself. So we can't use that path
|
||||
// we must use enumerator and search "." item
|
||||
CEnumerator enumerator;
|
||||
enumerator.SetDirPrefix(prefix);
|
||||
for (;;)
|
||||
{
|
||||
CFileInfo fi;
|
||||
if (!enumerator.NextAny(fi))
|
||||
break;
|
||||
if (fi.Name.IsEqualTo_Ascii_NoCase("."))
|
||||
{
|
||||
// we can copy preperies;
|
||||
CTime = fi.CTime;
|
||||
ATime = fi.ATime;
|
||||
MTime = fi.MTime;
|
||||
Attrib = fi.Attrib;
|
||||
Size = fi.Size;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// LastError(lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
NIO::CInFile inFile;
|
||||
if (inFile.Open(path))
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if (inFile.GetFileInformation(&info))
|
||||
{
|
||||
ClearBase();
|
||||
Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
|
||||
CTime = info.ftCreationTime;
|
||||
ATime = info.ftLastAccessTime;
|
||||
MTime = info.ftLastWriteTime;
|
||||
Attrib = info.dwFileAttributes;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool DoesFileExist_Raw(CFSTR name)
|
||||
{
|
||||
CFileInfo fi;
|
||||
return fi.Find(name) && !fi.IsDir();
|
||||
}
|
||||
|
||||
bool DoesDirExist(CFSTR name)
|
||||
bool DoesFileExist_FollowLink(CFSTR name)
|
||||
{
|
||||
CFileInfo fi;
|
||||
return fi.Find(name) && fi.IsDir();
|
||||
return fi.Find_FollowLink(name) && !fi.IsDir();
|
||||
}
|
||||
|
||||
bool DoesDirExist(CFSTR name, bool followLink)
|
||||
{
|
||||
CFileInfo fi;
|
||||
return fi.Find(name, followLink) && fi.IsDir();
|
||||
}
|
||||
|
||||
bool DoesFileOrDirExist(CFSTR name)
|
||||
@@ -645,15 +756,46 @@ bool CEnumerator::Next(CFileInfo &fi)
|
||||
|
||||
bool CEnumerator::Next(CFileInfo &fi, bool &found)
|
||||
{
|
||||
/*
|
||||
for (;;)
|
||||
{
|
||||
if (!NextAny(fi))
|
||||
break;
|
||||
if (!fi.IsDots())
|
||||
{
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (Next(fi))
|
||||
{
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
found = false;
|
||||
return (::GetLastError() == ERROR_NO_MORE_FILES);
|
||||
DWORD lastError = ::GetLastError();
|
||||
if (_findFile.IsHandleAllocated())
|
||||
return (lastError == ERROR_NO_MORE_FILES);
|
||||
// we support the case for empty root folder: FindFirstFile("c:\\*") returns ERROR_FILE_NOT_FOUND
|
||||
if (lastError == ERROR_FILE_NOT_FOUND)
|
||||
return true;
|
||||
if (lastError == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
// here we show inaccessible root system folder as empty folder to eliminate redundant user warnings
|
||||
const char *s = "System Volume Information" STRING_PATH_SEPARATOR "*";
|
||||
const int len = (int)strlen(s);
|
||||
const int delta = (int)_wildcard.Len() - len;
|
||||
if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1])))
|
||||
if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// CFindChangeNotification
|
||||
// FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
|
||||
@@ -744,6 +886,331 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // UNDER_CE
|
||||
|
||||
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// ---------- POSIX ----------
|
||||
|
||||
static int MY__lstat(CFSTR path, struct stat *st, bool followLink)
|
||||
{
|
||||
memset(st, 0, sizeof(*st));
|
||||
int res;
|
||||
// #ifdef ENV_HAVE_LSTAT
|
||||
if (/* global_use_lstat && */ !followLink)
|
||||
{
|
||||
// printf("\nlstat\n");
|
||||
res = lstat(path, st);
|
||||
}
|
||||
else
|
||||
// #endif
|
||||
{
|
||||
// printf("\nstat\n");
|
||||
res = stat(path, st);
|
||||
}
|
||||
/*
|
||||
printf("\nres = %d\n", res);
|
||||
printf("\n st_dev = %lld \n", (long long)(st->st_dev));
|
||||
printf("\n st_ino = %lld \n", (long long)(st->st_ino));
|
||||
printf("\n st_mode = %lld \n", (long long)(st->st_mode));
|
||||
printf("\n st_nlink = %lld \n", (long long)(st->st_nlink));
|
||||
printf("\n st_uid = %lld \n", (long long)(st->st_uid));
|
||||
printf("\n st_gid = %lld \n", (long long)(st->st_gid));
|
||||
printf("\n st_size = %lld \n", (long long)(st->st_size));
|
||||
printf("\n st_blksize = %lld \n", (long long)(st->st_blksize));
|
||||
printf("\n st_blocks = %lld \n", (long long)(st->st_blocks));
|
||||
*/
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static const char *Get_Name_from_Path(CFSTR path) throw()
|
||||
{
|
||||
size_t len = strlen(path);
|
||||
if (len == 0)
|
||||
return path;
|
||||
const char *p = path + len - 1;
|
||||
{
|
||||
if (p == path)
|
||||
return path;
|
||||
p--;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
char c = *p;
|
||||
if (IS_PATH_SEPAR(c))
|
||||
return p + 1;
|
||||
if (p == path)
|
||||
return path;
|
||||
p--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft)
|
||||
{
|
||||
UInt64 v = NTime::UnixTime64ToFileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
|
||||
ft.dwLowDateTime = (DWORD)v;
|
||||
ft.dwHighDateTime = (DWORD)(v >> 32);
|
||||
}
|
||||
|
||||
UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode)
|
||||
{
|
||||
UInt32 attrib = S_ISDIR(mode) ?
|
||||
FILE_ATTRIBUTE_DIRECTORY :
|
||||
FILE_ATTRIBUTE_ARCHIVE;
|
||||
if ((mode & 0222) == 0) // S_IWUSR in p7zip
|
||||
attrib |= FILE_ATTRIBUTE_READONLY;
|
||||
return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16);
|
||||
}
|
||||
|
||||
/*
|
||||
UInt32 Get_WinAttrib_From_stat(const struct stat &st)
|
||||
{
|
||||
UInt32 attrib = S_ISDIR(st.st_mode) ?
|
||||
FILE_ATTRIBUTE_DIRECTORY :
|
||||
FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
if ((st.st_mode & 0222) == 0) // check it !!!
|
||||
attrib |= FILE_ATTRIBUTE_READONLY;
|
||||
|
||||
attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16);
|
||||
return attrib;
|
||||
}
|
||||
*/
|
||||
|
||||
void CFileInfo::SetFrom_stat(const struct stat &st)
|
||||
{
|
||||
IsDevice = false;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
Size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename
|
||||
}
|
||||
|
||||
Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode);
|
||||
|
||||
// NTime::UnixTimeToFileTime(st.st_ctime, CTime);
|
||||
// NTime::UnixTimeToFileTime(st.st_mtime, MTime);
|
||||
// NTime::UnixTimeToFileTime(st.st_atime, ATime);
|
||||
#ifdef __APPLE__
|
||||
timespec_To_FILETIME(st.st_ctimespec, CTime);
|
||||
timespec_To_FILETIME(st.st_mtimespec, MTime);
|
||||
timespec_To_FILETIME(st.st_atimespec, ATime);
|
||||
#else
|
||||
timespec_To_FILETIME(st.st_ctim, CTime);
|
||||
timespec_To_FILETIME(st.st_mtim, MTime);
|
||||
timespec_To_FILETIME(st.st_atim, ATime);
|
||||
#endif
|
||||
|
||||
dev = st.st_dev;
|
||||
ino = st.st_ino;
|
||||
nlink = st.st_nlink;
|
||||
mode = st.st_mode;
|
||||
}
|
||||
|
||||
bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink)
|
||||
{
|
||||
struct stat st;
|
||||
if (MY__lstat(path, &st, followLink) != 0)
|
||||
return false;
|
||||
SetFrom_stat(st);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CFileInfo::Find(CFSTR path, bool followLink)
|
||||
{
|
||||
// printf("\nCEnumerator::Find() name = %s\n", path);
|
||||
if (!Find_DontFill_Name(path, followLink))
|
||||
return false;
|
||||
|
||||
// printf("\nOK\n");
|
||||
|
||||
Name = Get_Name_from_Path(path);
|
||||
if (!Name.IsEmpty())
|
||||
{
|
||||
char c = Name.Back();
|
||||
if (IS_PATH_SEPAR(c))
|
||||
Name.DeleteBack();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoesFileExist_Raw(CFSTR name)
|
||||
{
|
||||
// FIXME for symbolic links.
|
||||
struct stat st;
|
||||
if (MY__lstat(name, &st, false) != 0)
|
||||
return false;
|
||||
return !S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
bool DoesFileExist_FollowLink(CFSTR name)
|
||||
{
|
||||
// FIXME for symbolic links.
|
||||
struct stat st;
|
||||
if (MY__lstat(name, &st, true) != 0)
|
||||
return false;
|
||||
return !S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
bool DoesDirExist(CFSTR name, bool followLink)
|
||||
{
|
||||
struct stat st;
|
||||
if (MY__lstat(name, &st, followLink) != 0)
|
||||
return false;
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
bool DoesFileOrDirExist(CFSTR name)
|
||||
{
|
||||
struct stat st;
|
||||
if (MY__lstat(name, &st, false) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CEnumerator::~CEnumerator()
|
||||
{
|
||||
if (_dir)
|
||||
closedir(_dir);
|
||||
}
|
||||
|
||||
void CEnumerator::SetDirPrefix(const FString &dirPrefix)
|
||||
{
|
||||
_wildcard = dirPrefix;
|
||||
}
|
||||
|
||||
bool CDirEntry::IsDots() const throw()
|
||||
{
|
||||
if (
|
||||
#if !defined(_AIX)
|
||||
!IsDir() ||
|
||||
#endif
|
||||
Name.IsEmpty())
|
||||
return false;
|
||||
if (Name[0] != '.')
|
||||
return false;
|
||||
return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
|
||||
}
|
||||
|
||||
|
||||
bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
|
||||
{
|
||||
found = false;
|
||||
|
||||
if (!_dir)
|
||||
{
|
||||
const char *w = "./";
|
||||
if (!_wildcard.IsEmpty())
|
||||
w = _wildcard.Ptr();
|
||||
_dir = ::opendir((const char *)w);
|
||||
if (_dir == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
// To distinguish end of stream from an error, we must set errno to zero before readdir()
|
||||
errno = 0;
|
||||
|
||||
struct dirent *de = readdir(_dir);
|
||||
if (!de)
|
||||
{
|
||||
if (errno == 0)
|
||||
return true; // it's end of stream, and we report it with (found = false)
|
||||
// it's real error
|
||||
return false;
|
||||
}
|
||||
|
||||
fi.iNode = de->d_ino;
|
||||
|
||||
#if !defined(_AIX)
|
||||
fi.Type = de->d_type;
|
||||
#endif
|
||||
|
||||
/*
|
||||
if (de->d_type == DT_DIR)
|
||||
fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16);
|
||||
else if (de->d_type < 16)
|
||||
fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12));
|
||||
*/
|
||||
fi.Name = de->d_name;
|
||||
|
||||
/*
|
||||
printf("\nCEnumerator::NextAny; len = %d %s \n", (int)fi.Name.Len(), fi.Name.Ptr());
|
||||
for (unsigned i = 0; i < fi.Name.Len(); i++)
|
||||
printf (" %02x", (unsigned)(Byte)de->d_name[i]);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CEnumerator::Next(CDirEntry &fi, bool &found)
|
||||
{
|
||||
// printf("\nCEnumerator::Next()\n");
|
||||
// PrintName("Next", "");
|
||||
for (;;)
|
||||
{
|
||||
if (!NextAny(fi, found))
|
||||
return false;
|
||||
if (!found)
|
||||
return true;
|
||||
if (!fi.IsDots())
|
||||
{
|
||||
/*
|
||||
if (!NeedFullStat)
|
||||
return true;
|
||||
// we silently skip error file here - it can be wrong link item
|
||||
if (fi.Find_DontFill_Name(path))
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bool CEnumerator::Next(CDirEntry &fileInfo, bool &found)
|
||||
{
|
||||
bool found;
|
||||
if (!Next(fi, found))
|
||||
return false;
|
||||
return found;
|
||||
}
|
||||
*/
|
||||
|
||||
bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink)
|
||||
{
|
||||
// printf("\nCEnumerator::Fill_FileInfo()\n");
|
||||
struct stat st;
|
||||
// probably it's OK to use fstatat() even if it changes file position dirfd(_dir)
|
||||
int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW);
|
||||
// if fstatat() is not supported, we can use stat() / lstat()
|
||||
|
||||
/*
|
||||
const FString path = _wildcard + s;
|
||||
int res = MY__lstat(path, &st, followLink);
|
||||
*/
|
||||
|
||||
if (res != 0)
|
||||
return false;
|
||||
fileInfo.SetFrom_stat(st);
|
||||
fileInfo.Name = de.Name;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
}}}
|
||||
|
||||
@@ -3,13 +3,36 @@
|
||||
#ifndef __WINDOWS_FILE_FIND_H
|
||||
#define __WINDOWS_FILE_FIND_H
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "../Common/MyString.h"
|
||||
#include "../Common/MyWindows.h"
|
||||
#include "Defs.h"
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NFind {
|
||||
|
||||
// bool DoesFileExist(CFSTR name, bool followLink);
|
||||
bool DoesFileExist_Raw(CFSTR name);
|
||||
bool DoesFileExist_FollowLink(CFSTR name);
|
||||
bool DoesDirExist(CFSTR name, bool followLink);
|
||||
|
||||
inline bool DoesDirExist(CFSTR name)
|
||||
{ return DoesDirExist(name, false); }
|
||||
inline bool DoesDirExist_FollowLink(CFSTR name)
|
||||
{ return DoesDirExist(name, true); }
|
||||
|
||||
// it's always _Raw
|
||||
bool DoesFileOrDirExist(CFSTR name);
|
||||
|
||||
DWORD GetFileAttrib(CFSTR path);
|
||||
|
||||
|
||||
namespace NAttributes
|
||||
{
|
||||
inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; }
|
||||
@@ -33,6 +56,7 @@ public:
|
||||
bool IsAltStream;
|
||||
bool IsDevice;
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
#ifdef UNDER_CE
|
||||
DWORD ObjectID;
|
||||
@@ -40,11 +64,24 @@ public:
|
||||
UINT32 ReparseTag;
|
||||
#endif
|
||||
*/
|
||||
#else
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
nlink_t nlink;
|
||||
mode_t mode;
|
||||
// bool Use_lstat;
|
||||
#endif
|
||||
|
||||
CFileInfoBase() { ClearBase(); }
|
||||
void ClearBase() throw();
|
||||
|
||||
void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; }
|
||||
|
||||
void SetAsDir()
|
||||
{
|
||||
Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||
#ifndef _WIN32
|
||||
Attrib |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }
|
||||
bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }
|
||||
@@ -58,6 +95,14 @@ public:
|
||||
bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }
|
||||
bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }
|
||||
bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }
|
||||
|
||||
#ifndef _WIN32
|
||||
bool IsPosixLink() const
|
||||
{
|
||||
const UInt32 mod = Attrib >> 16;
|
||||
return S_ISLNK(mod);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct CFileInfo: public CFileInfoBase
|
||||
@@ -68,10 +113,22 @@ struct CFileInfo: public CFileInfoBase
|
||||
#endif
|
||||
|
||||
bool IsDots() const throw();
|
||||
bool Find(CFSTR path);
|
||||
bool Find(CFSTR path, bool followLink = false);
|
||||
bool Find_FollowLink(CFSTR path) { return Find(path, true); }
|
||||
|
||||
#ifdef _WIN32
|
||||
bool Fill_From_ByHandleFileInfo(CFSTR path);
|
||||
// bool FollowReparse(CFSTR path, bool isDir);
|
||||
#else
|
||||
bool Find_DontFill_Name(CFSTR path, bool followLink = false);
|
||||
void SetFrom_stat(const struct stat &st);
|
||||
#endif
|
||||
};
|
||||
|
||||
class CFindFileBase
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
class CFindFileBase MY_UNCOPYABLE
|
||||
{
|
||||
protected:
|
||||
HANDLE _handle;
|
||||
@@ -108,26 +165,21 @@ public:
|
||||
bool FindNext(CStreamInfo &streamInfo);
|
||||
};
|
||||
|
||||
class CStreamEnumerator
|
||||
class CStreamEnumerator MY_UNCOPYABLE
|
||||
{
|
||||
CFindStream _find;
|
||||
FString _filePath;
|
||||
|
||||
bool NextAny(CFileInfo &fileInfo);
|
||||
bool NextAny(CFileInfo &fileInfo, bool &found);
|
||||
public:
|
||||
CStreamEnumerator(const FString &filePath): _filePath(filePath) {}
|
||||
bool Next(CStreamInfo &streamInfo, bool &found);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
bool DoesFileExist(CFSTR name);
|
||||
bool DoesDirExist(CFSTR name);
|
||||
bool DoesFileOrDirExist(CFSTR name);
|
||||
|
||||
DWORD GetFileAttrib(CFSTR path);
|
||||
|
||||
class CEnumerator
|
||||
class CEnumerator MY_UNCOPYABLE
|
||||
{
|
||||
CFindFile _findFile;
|
||||
FString _wildcard;
|
||||
@@ -139,7 +191,8 @@ public:
|
||||
bool Next(CFileInfo &fileInfo, bool &found);
|
||||
};
|
||||
|
||||
class CFindChangeNotification
|
||||
|
||||
class CFindChangeNotification MY_UNCOPYABLE
|
||||
{
|
||||
HANDLE _handle;
|
||||
public:
|
||||
@@ -156,6 +209,71 @@ public:
|
||||
bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);
|
||||
#endif
|
||||
|
||||
typedef CFileInfo CDirEntry;
|
||||
|
||||
|
||||
#else // WIN32
|
||||
|
||||
|
||||
struct CDirEntry
|
||||
{
|
||||
ino_t iNode;
|
||||
#if !defined(_AIX)
|
||||
Byte Type;
|
||||
#endif
|
||||
FString Name;
|
||||
|
||||
#if !defined(_AIX)
|
||||
bool IsDir() const
|
||||
{
|
||||
// DT_DIR is
|
||||
return Type == DT_DIR;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsDots() const throw();
|
||||
};
|
||||
|
||||
class CEnumerator MY_UNCOPYABLE
|
||||
{
|
||||
DIR *_dir;
|
||||
FString _wildcard;
|
||||
|
||||
bool NextAny(CDirEntry &fileInfo, bool &found);
|
||||
public:
|
||||
CEnumerator(): _dir(NULL) {}
|
||||
~CEnumerator();
|
||||
void SetDirPrefix(const FString &dirPrefix);
|
||||
|
||||
bool Next(CDirEntry &fileInfo, bool &found);
|
||||
bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink);
|
||||
};
|
||||
|
||||
/*
|
||||
inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)
|
||||
{
|
||||
UInt32 attrib = S_ISDIR(mode) ?
|
||||
FILE_ATTRIBUTE_DIRECTORY :
|
||||
FILE_ATTRIBUTE_ARCHIVE;
|
||||
if ((st.st_mode & 0222) == 0) // check it !!!
|
||||
attrib |= FILE_ATTRIBUTE_READONLY;
|
||||
return attrib;
|
||||
}
|
||||
*/
|
||||
|
||||
UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode);
|
||||
|
||||
// UInt32 Get_WinAttrib_From_stat(const struct stat &st);
|
||||
#if defined(_AIX)
|
||||
#define MY_ST_TIMESPEC st_timespec
|
||||
#else
|
||||
#define MY_ST_TIMESPEC timespec
|
||||
#endif
|
||||
|
||||
void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft);
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,9 +6,21 @@
|
||||
#include "../../C/Alloc.h"
|
||||
#endif
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "FileIO.h"
|
||||
#include "FileName.h"
|
||||
|
||||
HRESULT GetLastError_noZero_HRESULT()
|
||||
{
|
||||
DWORD res = ::GetLastError();
|
||||
if (res == 0)
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32(res);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef _UNICODE
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
@@ -78,6 +90,42 @@ bool CFileBase::Create(CFSTR path, DWORD desiredAccess,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
#ifndef UNDER_CE
|
||||
#ifndef _SFX
|
||||
if (_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10
|
||||
DWORD lastError = GetLastError();
|
||||
if (lastError == ERROR_CANT_ACCESS_FILE)
|
||||
{
|
||||
CByteBuffer buf;
|
||||
if (NIO::GetReparseData(path, buf, NULL))
|
||||
{
|
||||
CReparseAttr attr;
|
||||
if (attr.Parse(buf, buf.Size()))
|
||||
{
|
||||
FString dirPrefix, fileName;
|
||||
if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName))
|
||||
{
|
||||
FString fullPath;
|
||||
if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath))
|
||||
{
|
||||
// FIX IT: recursion levels must be restricted
|
||||
return Create(fullPath, desiredAccess,
|
||||
shareMode, creationDisposition, flagsAndAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetLastError(lastError);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
|
||||
return (_handle != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
@@ -136,7 +184,7 @@ bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition
|
||||
|
||||
bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw()
|
||||
{
|
||||
return Seek(position, FILE_BEGIN, newPosition);
|
||||
return Seek((Int64)position, FILE_BEGIN, newPosition);
|
||||
}
|
||||
|
||||
bool CFileBase::SeekToBegin() const throw()
|
||||
@@ -258,7 +306,7 @@ void CInFile::CalcDeviceSize(CFSTR s)
|
||||
|
||||
if (GetPartitionInfo(&partInfo))
|
||||
{
|
||||
Size = partInfo.PartitionLength.QuadPart;
|
||||
Size = (UInt64)partInfo.PartitionLength.QuadPart;
|
||||
SizeDefined = true;
|
||||
needCorrectSize = false;
|
||||
if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0)
|
||||
@@ -277,7 +325,7 @@ void CInFile::CalcDeviceSize(CFSTR s)
|
||||
my_DISK_GEOMETRY_EX geomEx;
|
||||
SizeDefined = GetGeometryEx(&geomEx);
|
||||
if (SizeDefined)
|
||||
Size = geomEx.DiskSize.QuadPart;
|
||||
Size = (UInt64)geomEx.DiskSize.QuadPart;
|
||||
else
|
||||
{
|
||||
DISK_GEOMETRY geom;
|
||||
@@ -285,7 +333,7 @@ void CInFile::CalcDeviceSize(CFSTR s)
|
||||
if (!SizeDefined)
|
||||
SizeDefined = GetCdRomGeometry(&geom);
|
||||
if (SizeDefined)
|
||||
Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
|
||||
Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +358,24 @@ void CInFile::CalcDeviceSize(CFSTR s)
|
||||
|
||||
bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
|
||||
{
|
||||
bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);
|
||||
DWORD desiredAccess = GENERIC_READ;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (PreserveATime)
|
||||
desiredAccess |= FILE_WRITE_ATTRIBUTES;
|
||||
#endif
|
||||
|
||||
bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (res && PreserveATime)
|
||||
{
|
||||
FILETIME ft;
|
||||
ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF;
|
||||
::SetFileTime(_handle, NULL, &ft, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
MY_DEVICE_EXTRA_CODE
|
||||
return res;
|
||||
}
|
||||
@@ -330,7 +395,7 @@ bool CInFile::Open(CFSTR fileName)
|
||||
// for 32 MB (maybe also for 16 MB).
|
||||
// And message can be "Network connection was lost"
|
||||
|
||||
static UInt32 kChunkSizeMax = (1 << 22);
|
||||
static const UInt32 kChunkSizeMax = (1 << 22);
|
||||
|
||||
bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()
|
||||
{
|
||||
@@ -366,6 +431,26 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw()
|
||||
{
|
||||
processedSize = 0;
|
||||
do
|
||||
{
|
||||
UInt32 processedLoc = 0;
|
||||
const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size);
|
||||
const bool res = Read1(data, sizeLoc, processedLoc);
|
||||
processedSize += processedLoc;
|
||||
if (!res)
|
||||
return false;
|
||||
if (processedLoc == 0)
|
||||
return true;
|
||||
data = (void *)((unsigned char *)data + processedLoc);
|
||||
size -= processedLoc;
|
||||
}
|
||||
while (size > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------- COutFile ---------
|
||||
|
||||
static inline DWORD GetCreationDisposition(bool createAlways)
|
||||
@@ -430,3 +515,216 @@ bool COutFile::SetLength(UInt64 length) throw()
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
|
||||
// POSIX
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
|
||||
namespace NDir {
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
|
||||
}
|
||||
|
||||
namespace NIO {
|
||||
|
||||
bool CFileBase::OpenBinary(const char *name, int flags)
|
||||
{
|
||||
#ifdef O_BINARY
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
|
||||
Close();
|
||||
_handle = ::open(name, flags, 0666);
|
||||
return _handle != -1;
|
||||
}
|
||||
|
||||
bool CFileBase::Close()
|
||||
{
|
||||
if (_handle == -1)
|
||||
return true;
|
||||
if (close(_handle) != 0)
|
||||
return false;
|
||||
_handle = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFileBase::GetLength(UInt64 &length) const
|
||||
{
|
||||
const off_t curPos = seek(0, SEEK_CUR);
|
||||
if (curPos == -1)
|
||||
return false;
|
||||
const off_t lengthTemp = seek(0, SEEK_END);
|
||||
seek(curPos, SEEK_SET);
|
||||
length = (UInt64)lengthTemp;
|
||||
return (lengthTemp != -1);
|
||||
}
|
||||
|
||||
off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const
|
||||
{
|
||||
// printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove);
|
||||
// off_t res = ::lseek(_handle, distanceToMove, moveMethod);
|
||||
return ::lseek(_handle, distanceToMove, moveMethod);
|
||||
// printf(" res = %lld", (long long)res);
|
||||
// return res;
|
||||
}
|
||||
|
||||
off_t CFileBase::seekToBegin() const throw()
|
||||
{
|
||||
return seek(0, SEEK_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CFileBase::SeekToBegin() const throw()
|
||||
{
|
||||
return (::seek(0, SEEK_SET) != -1);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/////////////////////////
|
||||
// CInFile
|
||||
|
||||
bool CInFile::Open(const char *name)
|
||||
{
|
||||
return CFileBase::OpenBinary(name, O_RDONLY);
|
||||
}
|
||||
|
||||
bool CInFile::OpenShared(const char *name, bool)
|
||||
{
|
||||
return Open(name);
|
||||
}
|
||||
|
||||
/*
|
||||
On Linux (32-bit and 64-bit):
|
||||
read(), write() (and similar system calls) will transfer at most
|
||||
0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred.
|
||||
*/
|
||||
|
||||
static const size_t kChunkSizeMax = ((size_t)1 << 22);
|
||||
|
||||
ssize_t CInFile::read_part(void *data, size_t size) throw()
|
||||
{
|
||||
if (size > kChunkSizeMax)
|
||||
size = kChunkSizeMax;
|
||||
return ::read(_handle, data, size);
|
||||
}
|
||||
|
||||
bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw()
|
||||
{
|
||||
processed = 0;
|
||||
do
|
||||
{
|
||||
const ssize_t res = read_part(data, size);
|
||||
if (res < 0)
|
||||
return false;
|
||||
if (res == 0)
|
||||
break;
|
||||
data = (void *)((unsigned char *)data + (size_t)res);
|
||||
size -= (size_t)res;
|
||||
processed += (size_t)res;
|
||||
}
|
||||
while (size > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////
|
||||
// COutFile
|
||||
|
||||
bool COutFile::Create(const char *name, bool createAlways)
|
||||
{
|
||||
Path = name; // change it : set it only if open is success.
|
||||
if (createAlways)
|
||||
{
|
||||
Close();
|
||||
_handle = ::creat(name, 0666);
|
||||
return _handle != -1;
|
||||
}
|
||||
return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY);
|
||||
}
|
||||
|
||||
bool COutFile::Open(const char *name, DWORD creationDisposition)
|
||||
{
|
||||
UNUSED_VAR(creationDisposition) // FIXME
|
||||
return Create(name, false);
|
||||
}
|
||||
|
||||
ssize_t COutFile::write_part(const void *data, size_t size) throw()
|
||||
{
|
||||
if (size > kChunkSizeMax)
|
||||
size = kChunkSizeMax;
|
||||
return ::write(_handle, data, size);
|
||||
}
|
||||
|
||||
ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw()
|
||||
{
|
||||
processed = 0;
|
||||
do
|
||||
{
|
||||
const ssize_t res = write_part(data, size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (res == 0)
|
||||
break;
|
||||
data = (const void *)((const unsigned char *)data + (size_t)res);
|
||||
size -= (size_t)res;
|
||||
processed += (size_t)res;
|
||||
}
|
||||
while (size > 0);
|
||||
return (ssize_t)processed;
|
||||
}
|
||||
|
||||
bool COutFile::SetLength(UInt64 length) throw()
|
||||
{
|
||||
const off_t len2 = (off_t)length;
|
||||
if ((Int64)length != len2)
|
||||
{
|
||||
SetLastError(EFBIG);
|
||||
return false;
|
||||
}
|
||||
int iret = ftruncate(_handle, len2);
|
||||
return (iret == 0);
|
||||
}
|
||||
|
||||
bool COutFile::Close()
|
||||
{
|
||||
bool res = CFileBase::Close();
|
||||
if (!res)
|
||||
return res;
|
||||
if (CTime_defined || ATime_defined || MTime_defined)
|
||||
{
|
||||
/* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path,
|
||||
CTime_defined ? &CTime : NULL,
|
||||
ATime_defined ? &ATime : NULL,
|
||||
MTime_defined ? &MTime : NULL);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()
|
||||
{
|
||||
// On some OS (cygwin, MacOSX ...), you must close the file before updating times
|
||||
// return true;
|
||||
|
||||
if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false;
|
||||
if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false;
|
||||
if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COutFile::SetMTime(const FILETIME *mTime) throw()
|
||||
{
|
||||
if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,26 @@
|
||||
|
||||
#include "../Common/MyWindows.h"
|
||||
|
||||
#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
|
||||
#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||
#define _my_IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL)
|
||||
|
||||
#define _my_SYMLINK_FLAG_RELATIVE 1
|
||||
|
||||
// what the meaning of that FLAG or field (2)?
|
||||
#define _my_LX_SYMLINK_FLAG 2
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
#include <winioctl.h>
|
||||
#include <WinIoCtl.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "../Common/MyString.h"
|
||||
@@ -14,19 +32,17 @@
|
||||
|
||||
#include "Defs.h"
|
||||
|
||||
#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
|
||||
#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||
HRESULT GetLastError_noZero_HRESULT();
|
||||
|
||||
#define _my_SYMLINK_FLAG_RELATIVE 1
|
||||
|
||||
#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER
|
||||
#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER
|
||||
#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER
|
||||
#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER
|
||||
#define my_FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink);
|
||||
bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL);
|
||||
#endif
|
||||
|
||||
struct CReparseShortInfo
|
||||
@@ -44,28 +60,50 @@ struct CReparseAttr
|
||||
UString SubsName;
|
||||
UString PrintName;
|
||||
|
||||
AString WslName;
|
||||
|
||||
bool HeaderError;
|
||||
bool TagIsUnknown;
|
||||
bool MinorError;
|
||||
DWORD ErrorCode;
|
||||
|
||||
CReparseAttr(): Tag(0), Flags(0) {}
|
||||
|
||||
// Parse()
|
||||
// returns true and (errorCode = 0), if (correct MOUNT_POINT or SYMLINK)
|
||||
// returns false and (errorCode = ERROR_REPARSE_TAG_MISMATCH), if not (MOUNT_POINT or SYMLINK)
|
||||
bool Parse(const Byte *p, size_t size, DWORD &errorCode);
|
||||
// returns (true) and (ErrorCode = 0), if (it'a correct known link)
|
||||
// returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag
|
||||
bool Parse(const Byte *p, size_t size);
|
||||
|
||||
bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
|
||||
bool IsSymLink_Win() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
|
||||
bool IsSymLink_WSL() const { return Tag == _my_IO_REPARSE_TAG_LX_SYMLINK; }
|
||||
|
||||
bool IsRelative_Win() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; }
|
||||
|
||||
bool IsRelative_WSL() const
|
||||
{
|
||||
if (WslName.IsEmpty())
|
||||
return true;
|
||||
char c = WslName[0];
|
||||
return !IS_PATH_SEPAR(c);
|
||||
}
|
||||
|
||||
bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
|
||||
bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
|
||||
bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; }
|
||||
// bool IsVolume() const;
|
||||
|
||||
bool IsOkNamePair() const;
|
||||
UString GetPath() const;
|
||||
};
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
namespace NIO {
|
||||
|
||||
bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);
|
||||
bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
|
||||
bool DeleteReparseData(CFSTR path);
|
||||
|
||||
class CFileBase
|
||||
class CFileBase MY_UNCOPYABLE
|
||||
{
|
||||
protected:
|
||||
HANDLE _handle;
|
||||
@@ -94,13 +132,14 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
bool PreserveATime;
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
bool IsDeviceFile;
|
||||
bool SizeDefined;
|
||||
UInt64 Size; // it can be larger than real available size
|
||||
#endif
|
||||
|
||||
CFileBase(): _handle(INVALID_HANDLE_VALUE) {};
|
||||
CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {};
|
||||
~CFileBase() { Close(); }
|
||||
|
||||
bool Close() throw();
|
||||
@@ -118,6 +157,7 @@ public:
|
||||
|
||||
static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info)
|
||||
{
|
||||
// probably it can work for complex paths: unsupported by another things
|
||||
NIO::CFileBase file;
|
||||
if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS))
|
||||
return false;
|
||||
@@ -189,6 +229,7 @@ public:
|
||||
bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw();
|
||||
bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw();
|
||||
bool Read(void *data, UInt32 size, UInt32 &processedSize) throw();
|
||||
bool ReadFull(void *data, size_t size, size_t &processedSize) throw();
|
||||
};
|
||||
|
||||
class COutFile: public CFileBase
|
||||
@@ -207,6 +248,83 @@ public:
|
||||
bool SetLength(UInt64 length) throw();
|
||||
};
|
||||
|
||||
}}}
|
||||
}
|
||||
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
namespace NIO {
|
||||
|
||||
bool GetReparseData(CFSTR path, CByteBuffer &reparseData);
|
||||
// bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
|
||||
|
||||
// parameters are in reverse order of symlink() function !!!
|
||||
bool SetSymLink(CFSTR from, CFSTR to);
|
||||
bool SetSymLink_UString(CFSTR from, const UString &to);
|
||||
|
||||
|
||||
class CFileBase
|
||||
{
|
||||
protected:
|
||||
int _handle;
|
||||
|
||||
bool OpenBinary(const char *name, int flags);
|
||||
public:
|
||||
bool PreserveATime;
|
||||
|
||||
CFileBase(): _handle(-1), PreserveATime(false) {};
|
||||
~CFileBase() { Close(); }
|
||||
bool Close();
|
||||
bool GetLength(UInt64 &length) const;
|
||||
off_t seek(off_t distanceToMove, int moveMethod) const;
|
||||
off_t seekToBegin() const throw();
|
||||
// bool SeekToBegin() throw();
|
||||
int my_fstat(struct stat *st) const { return fstat(_handle, st); }
|
||||
};
|
||||
|
||||
class CInFile: public CFileBase
|
||||
{
|
||||
public:
|
||||
bool Open(const char *name);
|
||||
bool OpenShared(const char *name, bool shareForWrite);
|
||||
ssize_t read_part(void *data, size_t size) throw();
|
||||
// ssize_t read_full(void *data, size_t size, size_t &processed);
|
||||
bool ReadFull(void *data, size_t size, size_t &processedSize) throw();
|
||||
};
|
||||
|
||||
class COutFile: public CFileBase
|
||||
{
|
||||
bool CTime_defined;
|
||||
bool ATime_defined;
|
||||
bool MTime_defined;
|
||||
|
||||
FILETIME CTime;
|
||||
FILETIME ATime;
|
||||
FILETIME MTime;
|
||||
|
||||
AString Path;
|
||||
ssize_t write_part(const void *data, size_t size) throw();
|
||||
public:
|
||||
COutFile():
|
||||
CTime_defined(false),
|
||||
ATime_defined(false),
|
||||
MTime_defined(false)
|
||||
{}
|
||||
|
||||
bool Close();
|
||||
bool Create(const char *name, bool createAlways);
|
||||
bool Open(const char *name, DWORD creationDisposition);
|
||||
ssize_t write_full(const void *data, size_t size, size_t &processed) throw();
|
||||
bool SetLength(UInt64 length) throw();
|
||||
bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();
|
||||
bool SetMTime(const FILETIME *mTime) throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,10 +4,17 @@
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#include "../../C/Alloc.h"
|
||||
#endif
|
||||
|
||||
#include "../Common/UTFConvert.h"
|
||||
#include "../Common/StringConvert.h"
|
||||
|
||||
#include "FileDir.h"
|
||||
#include "FileFind.h"
|
||||
#include "FileIO.h"
|
||||
@@ -54,6 +61,12 @@ using namespace NName;
|
||||
Substitute Path
|
||||
*/
|
||||
|
||||
/*
|
||||
Win10 WSL2:
|
||||
admin rights + sudo: it creates normal windows symbolic link.
|
||||
in another cases : it creates IO_REPARSE_TAG_LX_SYMLINK repare point.
|
||||
*/
|
||||
|
||||
/*
|
||||
static const UInt32 kReparseFlags_Alias = (1 << 29);
|
||||
static const UInt32 kReparseFlags_HighLatency = (1 << 30);
|
||||
@@ -71,13 +84,10 @@ static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31);
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
|
||||
#define Set16(p, v) SetUi16(p, v)
|
||||
#define Set32(p, v) SetUi32(p, v)
|
||||
|
||||
static const wchar_t * const k_LinkPrefix = L"\\??\\";
|
||||
static const unsigned k_LinkPrefix_Size = 4;
|
||||
|
||||
static const bool IsLinkPrefix(const wchar_t *s)
|
||||
static bool IsLinkPrefix(const wchar_t *s)
|
||||
{
|
||||
return IsString1PrefixedByString2(s, k_LinkPrefix);
|
||||
}
|
||||
@@ -90,7 +100,12 @@ static const bool IsVolumeName(const wchar_t *s)
|
||||
}
|
||||
*/
|
||||
|
||||
void WriteString(Byte *dest, const wchar_t *path)
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
#define Set16(p, v) SetUi16(p, v)
|
||||
#define Set32(p, v) SetUi32(p, v)
|
||||
|
||||
static void WriteString(Byte *dest, const wchar_t *path)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -102,14 +117,32 @@ void WriteString(Byte *dest, const wchar_t *path)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL)
|
||||
{
|
||||
bool isAbs = IsAbsolutePath(path);
|
||||
if (!isAbs && !isSymLink)
|
||||
return false;
|
||||
|
||||
if (isWSL)
|
||||
{
|
||||
// unsupported characters probably use Replacement Character UTF-16 0xFFFD
|
||||
AString utf;
|
||||
ConvertUnicodeToUTF8(path, utf);
|
||||
const size_t size = 4 + utf.Len();
|
||||
if (size != (UInt16)size)
|
||||
return false;
|
||||
dest.Alloc(8 + size);
|
||||
Byte *p = dest;
|
||||
Set32(p, _my_IO_REPARSE_TAG_LX_SYMLINK);
|
||||
Set16(p + 4, (UInt16)(size));
|
||||
Set16(p + 6, 0);
|
||||
Set32(p + 8, _my_LX_SYMLINK_FLAG);
|
||||
memcpy(p + 12, utf.Ptr(), utf.Len());
|
||||
return true;
|
||||
}
|
||||
|
||||
// usual symbolic LINK (NOT WSL)
|
||||
|
||||
bool needPrintName = true;
|
||||
|
||||
if (IsSuperPath(path))
|
||||
@@ -121,12 +154,12 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
|
||||
const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0;
|
||||
|
||||
unsigned len2 = MyStringLen(path) * 2;
|
||||
const unsigned len1 = len2 + add_Prefix_Len * 2;
|
||||
size_t len2 = (size_t)MyStringLen(path) * 2;
|
||||
const size_t len1 = len2 + add_Prefix_Len * 2;
|
||||
if (!needPrintName)
|
||||
len2 = 0;
|
||||
|
||||
unsigned totalNamesSize = (len1 + len2);
|
||||
size_t totalNamesSize = (len1 + len2);
|
||||
|
||||
/* some WIM imagex software uses old scheme for symbolic links.
|
||||
so we can old scheme for byte to byte compatibility */
|
||||
@@ -138,6 +171,8 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
totalNamesSize += 2 * 2;
|
||||
|
||||
const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize;
|
||||
if (size != (UInt16)size)
|
||||
return false;
|
||||
dest.Alloc(size);
|
||||
memset(dest, 0, size);
|
||||
const UInt32 tag = isSymLink ?
|
||||
@@ -152,9 +187,9 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
unsigned subOffs = 0;
|
||||
unsigned printOffs = 0;
|
||||
if (newOrderScheme)
|
||||
subOffs = len2;
|
||||
subOffs = (unsigned)len2;
|
||||
else
|
||||
printOffs = len1 + 2;
|
||||
printOffs = (unsigned)len1 + 2;
|
||||
|
||||
Set16(p + 0, (UInt16)subOffs);
|
||||
Set16(p + 2, (UInt16)len1);
|
||||
@@ -177,7 +212,8 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
|
||||
static void GetString(const Byte *p, unsigned len, UString &res)
|
||||
{
|
||||
@@ -194,35 +230,69 @@ static void GetString(const Byte *p, unsigned len, UString &res)
|
||||
res.ReleaseBuf_SetLen(i);
|
||||
}
|
||||
|
||||
bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode)
|
||||
bool CReparseAttr::Parse(const Byte *p, size_t size)
|
||||
{
|
||||
errorCode = ERROR_INVALID_REPARSE_DATA;
|
||||
ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA;
|
||||
HeaderError = true;
|
||||
TagIsUnknown = true;
|
||||
MinorError = false;
|
||||
|
||||
if (size < 8)
|
||||
return false;
|
||||
Tag = Get32(p);
|
||||
UInt32 len = Get16(p + 4);
|
||||
if (len + 8 > size)
|
||||
if (len + 8 != size)
|
||||
// if (len + 8 > size)
|
||||
return false;
|
||||
/*
|
||||
if ((type & kReparseFlags_Alias) == 0 ||
|
||||
(type & kReparseFlags_Microsoft) == 0 ||
|
||||
(type & 0xFFFF) != 3)
|
||||
*/
|
||||
if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT &&
|
||||
Tag != _my_IO_REPARSE_TAG_SYMLINK)
|
||||
{
|
||||
errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Get16(p + 6) != 0) // padding
|
||||
return false;
|
||||
|
||||
|
||||
HeaderError = false;
|
||||
|
||||
if ( Tag != _my_IO_REPARSE_TAG_MOUNT_POINT
|
||||
&& Tag != _my_IO_REPARSE_TAG_SYMLINK
|
||||
&& Tag != _my_IO_REPARSE_TAG_LX_SYMLINK)
|
||||
{
|
||||
// for unsupported reparse points
|
||||
ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH
|
||||
// errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID
|
||||
return false;
|
||||
}
|
||||
|
||||
TagIsUnknown = false;
|
||||
|
||||
p += 8;
|
||||
size -= 8;
|
||||
|
||||
if (len != size) // do we need that check?
|
||||
return false;
|
||||
if (Tag == _my_IO_REPARSE_TAG_LX_SYMLINK)
|
||||
{
|
||||
if (len < 4)
|
||||
return false;
|
||||
Flags = Get32(p); // maybe it's not Flags
|
||||
if (Flags != _my_LX_SYMLINK_FLAG)
|
||||
return false;
|
||||
len -= 4;
|
||||
p += 4;
|
||||
char *s = WslName.GetBuf(len);
|
||||
unsigned i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
char c = (char)p[i];
|
||||
s[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
WslName.ReleaseBuf_SetEnd(i);
|
||||
MinorError = (i != len);
|
||||
ErrorCode = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (len < 8)
|
||||
return false;
|
||||
@@ -250,10 +320,11 @@ bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode)
|
||||
GetString(p + subOffs, subLen >> 1, SubsName);
|
||||
GetString(p + printOffs, printLen >> 1, PrintName);
|
||||
|
||||
errorCode = 0;
|
||||
ErrorCode = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CReparseShortInfo::Parse(const Byte *p, size_t size)
|
||||
{
|
||||
const Byte *start = p;
|
||||
@@ -336,26 +407,34 @@ bool CReparseAttr::IsVolume() const
|
||||
|
||||
UString CReparseAttr::GetPath() const
|
||||
{
|
||||
if (IsSymLink_WSL())
|
||||
{
|
||||
UString u;
|
||||
// if (CheckUTF8(attr.WslName)
|
||||
if (!ConvertUTF8ToUnicode(WslName, u))
|
||||
MultiByteToUnicodeString2(u, WslName);
|
||||
return u;
|
||||
}
|
||||
|
||||
UString s (SubsName);
|
||||
if (IsLinkPrefix(s))
|
||||
{
|
||||
s.ReplaceOneCharAtPos(1, '\\');
|
||||
s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\"
|
||||
if (IsDrivePath(s.Ptr(k_LinkPrefix_Size)))
|
||||
s.DeleteFrontal(k_LinkPrefix_Size);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
|
||||
namespace NSystem
|
||||
{
|
||||
bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
|
||||
}
|
||||
#endif
|
||||
#endif // SUPPORT_DEVICE_FILE
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
namespace NIO {
|
||||
|
||||
@@ -388,11 +467,26 @@ static bool CreatePrefixDirOfFile(CFSTR path)
|
||||
if (pos == 2 && path2[1] == L':')
|
||||
return true; // we don't create Disk folder;
|
||||
#endif
|
||||
path2.DeleteFrom(pos);
|
||||
path2.DeleteFrom((unsigned)pos);
|
||||
return NDir::CreateComplexDir(path2);
|
||||
}
|
||||
|
||||
// If there is Reprase data already, it still writes new Reparse data
|
||||
|
||||
static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size)
|
||||
{
|
||||
COutFile file;
|
||||
if (!file.Open(path,
|
||||
FILE_SHARE_WRITE,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))
|
||||
return false;
|
||||
|
||||
DWORD returnedSize;
|
||||
return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize);
|
||||
}
|
||||
|
||||
|
||||
// If there is Reparse data already, it still writes new Reparse data
|
||||
bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
|
||||
{
|
||||
NFile::NFind::CFileInfo fi;
|
||||
@@ -420,21 +514,100 @@ bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
|
||||
}
|
||||
}
|
||||
|
||||
COutFile file;
|
||||
if (!file.Open(path,
|
||||
FILE_SHARE_WRITE,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))
|
||||
return false;
|
||||
return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size);
|
||||
}
|
||||
|
||||
DWORD returnedSize;
|
||||
if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize))
|
||||
|
||||
bool DeleteReparseData(CFSTR path)
|
||||
{
|
||||
CByteBuffer reparseData;
|
||||
if (!GetReparseData(path, reparseData, NULL))
|
||||
return false;
|
||||
/* MSDN: The tag specified in the ReparseTag member of this structure
|
||||
must match the tag of the reparse point to be deleted,
|
||||
and the ReparseDataLength member must be zero */
|
||||
#define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8
|
||||
if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_REPARSE_DATA);
|
||||
return false;
|
||||
}
|
||||
BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memcpy(buf, reparseData, 4); // tag
|
||||
return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
namespace NIO {
|
||||
|
||||
bool GetReparseData(CFSTR path, CByteBuffer &reparseData)
|
||||
{
|
||||
reparseData.Free();
|
||||
|
||||
#define MAX_PATHNAME_LEN 1024
|
||||
char buf[MAX_PATHNAME_LEN + 2];
|
||||
const size_t request = sizeof(buf) - 1;
|
||||
|
||||
// printf("\nreadlink() path = %s \n", path);
|
||||
const ssize_t size = readlink(path, buf, request);
|
||||
// there is no tail zero
|
||||
|
||||
if (size < 0)
|
||||
return false;
|
||||
if ((size_t)size >= request)
|
||||
{
|
||||
SetLastError(EINVAL); // check it: ENAMETOOLONG
|
||||
return false;
|
||||
}
|
||||
|
||||
// printf("\nreadlink() res = %s size = %d \n", buf, (int)size);
|
||||
reparseData.CopyFrom((const Byte *)buf, (size_t)size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// If there is Reparse data already, it still writes new Reparse data
|
||||
bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
|
||||
{
|
||||
// AString s;
|
||||
// s.SetFrom_CalcLen(data, size);
|
||||
// return (symlink(s, path) == 0);
|
||||
UNUSED_VAR(path)
|
||||
UNUSED_VAR(isDir)
|
||||
UNUSED_VAR(data)
|
||||
UNUSED_VAR(size)
|
||||
SetLastError(ENOSYS);
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
bool SetSymLink(CFSTR from, CFSTR to)
|
||||
{
|
||||
// printf("\nsymlink() %s -> %s\n", from, to);
|
||||
int ir;
|
||||
// ir = unlink(path);
|
||||
// if (ir == 0)
|
||||
ir = symlink(to, from);
|
||||
return (ir == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
bool SetSymLink_UString(CFSTR from, const UString &to)
|
||||
{
|
||||
AString utf;
|
||||
ConvertUnicodeToUTF8(to, utf);
|
||||
return SetSymLink(from, utf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
}}
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include "../Common/StringConvert.h"
|
||||
#endif
|
||||
|
||||
#include "FileName.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
@@ -58,7 +64,18 @@ void NormalizeDirPathPrefix(UString &dirPath)
|
||||
dirPath.Add_PathSepar();
|
||||
}
|
||||
|
||||
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
|
||||
#ifdef _WIN32
|
||||
void NormalizeDirSeparators(FString &s)
|
||||
{
|
||||
const unsigned len = s.Len();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (s[i] == '/')
|
||||
s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
|
||||
|
||||
bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
|
||||
|
||||
@@ -88,7 +105,9 @@ bool IsAltPathPrefix(CFSTR s) throw()
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
const char * const kSuperPathPrefix = "\\\\?\\";
|
||||
#ifdef WIN_LONG_PATH
|
||||
static const char * const kSuperUncPrefix = "\\\\?\\UNC\\";
|
||||
#endif
|
||||
|
||||
#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
|
||||
#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
|
||||
@@ -160,7 +179,7 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
|
||||
int pos = FindSepar(s + prefixSize);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
return prefixSize + pos + 1;
|
||||
return prefixSize + (unsigned)(pos + 1);
|
||||
}
|
||||
|
||||
bool IsNetworkShareRootPath(CFSTR s) throw()
|
||||
@@ -224,7 +243,7 @@ int FindAltStreamColon(CFSTR path) throw()
|
||||
if (c == ':')
|
||||
{
|
||||
if (colonPos < 0)
|
||||
colonPos = i;
|
||||
colonPos = (int)i;
|
||||
continue;
|
||||
}
|
||||
if (IS_SEPAR(c))
|
||||
@@ -292,7 +311,7 @@ static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
|
||||
int pos2 = FindSepar(s + (unsigned)pos + 1);
|
||||
if (pos2 < 0)
|
||||
return 0;
|
||||
return pos + pos2 + 2;
|
||||
return (unsigned)(pos + pos2 + 2);
|
||||
}
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
|
||||
@@ -318,7 +337,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
|
||||
int pos = FindSepar(s + kSuperPathPrefixSize);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
return kSuperPathPrefixSize + pos + 1;
|
||||
return kSuperPathPrefixSize + (unsigned)(pos + 1);
|
||||
}
|
||||
|
||||
unsigned GetRootPrefixSize(const wchar_t *s) throw()
|
||||
@@ -332,12 +351,13 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw()
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }
|
||||
bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); }
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
unsigned GetRootPrefixSize(CFSTR s) throw();
|
||||
unsigned GetRootPrefixSize(CFSTR s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
#endif
|
||||
unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
unsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
@@ -347,6 +367,9 @@ unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
static bool GetCurDir(UString &path)
|
||||
{
|
||||
path.Empty();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
DWORD needLength;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -365,6 +388,23 @@ static bool GetCurDir(UString &path)
|
||||
path = s;
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
|
||||
#else
|
||||
|
||||
#define MY__PATH_MAX PATH_MAX
|
||||
// #define MY__PATH_MAX 1024
|
||||
|
||||
char s[MY__PATH_MAX + 1];
|
||||
char *res = getcwd(s, MY__PATH_MAX);
|
||||
if (!res)
|
||||
{
|
||||
// if (errno != ERANGE)
|
||||
return false;
|
||||
}
|
||||
path = GetUnicodeString(s);
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool ResolveDotsFolders(UString &s)
|
||||
@@ -388,7 +428,7 @@ static bool ResolveDotsFolders(UString &s)
|
||||
{
|
||||
if (i == 0)
|
||||
return false;
|
||||
int k = i - 2;
|
||||
int k = (int)i - 2;
|
||||
i += 2;
|
||||
|
||||
for (;; k--)
|
||||
@@ -407,8 +447,8 @@ static bool ResolveDotsFolders(UString &s)
|
||||
|
||||
if (k >= 0)
|
||||
{
|
||||
num = i - k;
|
||||
i = k;
|
||||
num = i - (unsigned)k;
|
||||
i = (unsigned)k;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -528,6 +568,7 @@ int GetUseSuperPathType(CFSTR s) throw()
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
returns false in two cases:
|
||||
- if GetCurDir was used, and GetCurDir returned error.
|
||||
@@ -538,7 +579,6 @@ int GetUseSuperPathType(CFSTR s) throw()
|
||||
for absolute paths, returns true, res is Super path.
|
||||
*/
|
||||
|
||||
|
||||
static bool GetSuperPathBase(CFSTR s, UString &res)
|
||||
{
|
||||
res.Empty();
|
||||
@@ -702,6 +742,8 @@ bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew)
|
||||
return false;
|
||||
superPath = fs2us(path);
|
||||
}
|
||||
|
||||
NormalizeDirSeparators(superPath);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -712,6 +754,10 @@ bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew)
|
||||
if (!GetSuperPathBase(s1, d1) ||
|
||||
!GetSuperPathBase(s2, d2))
|
||||
return false;
|
||||
|
||||
NormalizeDirSeparators(d1);
|
||||
NormalizeDirSeparators(d2);
|
||||
|
||||
if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew)
|
||||
return false;
|
||||
if (d1.IsEmpty()) d1 = fs2us(s1);
|
||||
|
||||
@@ -17,6 +17,10 @@ int FindSepar(const FChar *s) throw();
|
||||
void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty
|
||||
void NormalizeDirPathPrefix(UString &dirPath);
|
||||
|
||||
#ifdef _WIN32
|
||||
void NormalizeDirSeparators(FString &s);
|
||||
#endif
|
||||
|
||||
bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\"
|
||||
|
||||
bool IsAltPathPrefix(CFSTR s) throw(); /* name: */
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NSystem {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool MyGetVolumeInformation(
|
||||
CFSTR rootPath,
|
||||
UString &volumeName,
|
||||
@@ -90,7 +92,7 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)GetProcAddress(
|
||||
GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)(void *)GetProcAddress(
|
||||
GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA");
|
||||
if (pGetDiskFreeSpaceEx)
|
||||
{
|
||||
@@ -105,7 +107,7 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)GetProcAddress(
|
||||
GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)(void *)GetProcAddress(
|
||||
GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW");
|
||||
if (pGetDiskFreeSpaceEx)
|
||||
{
|
||||
@@ -126,6 +128,8 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NSystem {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool MyGetVolumeInformation(
|
||||
CFSTR rootPath ,
|
||||
UString &volumeName,
|
||||
@@ -22,6 +24,8 @@ UINT MyGetDriveType(CFSTR pathName);
|
||||
|
||||
bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
|
||||
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
#ifndef __WINDOWS_HANDLE_H
|
||||
#define __WINDOWS_HANDLE_H
|
||||
|
||||
#include "../Common/MyTypes.h"
|
||||
|
||||
namespace NWindows {
|
||||
|
||||
class CHandle
|
||||
class CHandle MY_UNCOPYABLE
|
||||
{
|
||||
protected:
|
||||
HANDLE _handle;
|
||||
|
||||
@@ -75,11 +75,11 @@ typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
|
||||
|
||||
/*
|
||||
We suppose that Window 10 works incorrectly with "Large Pages" at:
|
||||
- Windows 10 1703 (15063)
|
||||
- Windows 10 1709 (16299)
|
||||
|
||||
- Windows 10 1809 (17763) on some CPUs that have no 1 GB page support.
|
||||
We need more information about that new BUG in Windows.
|
||||
- Windows 10 1703 (15063) : incorrect allocating after VirtualFree()
|
||||
- Windows 10 1709 (16299) : incorrect allocating after VirtualFree()
|
||||
- Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger,
|
||||
if CPU doesn't support 1 GB pages.
|
||||
Windows 10 1903 (18362) probably works correctly.
|
||||
*/
|
||||
|
||||
unsigned Get_LargePages_RiskLevel()
|
||||
@@ -88,7 +88,7 @@ unsigned Get_LargePages_RiskLevel()
|
||||
HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
|
||||
if (!ntdll)
|
||||
return 0;
|
||||
Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion");
|
||||
Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion");
|
||||
if (!func)
|
||||
return 0;
|
||||
func(&vi);
|
||||
@@ -100,7 +100,7 @@ unsigned Get_LargePages_RiskLevel()
|
||||
return 1;
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (!CPU_IsSupported_PageGB())
|
||||
if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB())
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -26,11 +26,15 @@ will not work at NT 4.0, if cbSize is set as sizeof(MENUITEMINFO*).
|
||||
So we use size of old version of structure. */
|
||||
|
||||
#if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500)
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_MENUITEMINFOA_size sizeof(MENUITEMINFOA)
|
||||
#endif
|
||||
#define my_compatib_MENUITEMINFOW_size sizeof(MENUITEMINFOW)
|
||||
#else
|
||||
#define MY_STRUCT_SIZE_BEFORE(structname, member) ((UINT)(UINT_PTR)((LPBYTE)(&((structname*)0)->member) - (LPBYTE)(structname*)0))
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem)
|
||||
#endif
|
||||
#define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem)
|
||||
#endif
|
||||
|
||||
@@ -145,7 +149,7 @@ bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
|
||||
if (item.IsString())
|
||||
{
|
||||
s = GetSystemString(item.StringValue);
|
||||
si.dwTypeData = (LPTSTR)(LPCTSTR)s;
|
||||
si.dwTypeData = s.Ptr_non_const();
|
||||
}
|
||||
return SetItemInfo(itemIndex, byPosition, &si);
|
||||
}
|
||||
@@ -155,7 +159,7 @@ bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
|
||||
MENUITEMINFOW si;
|
||||
ConvertItemToSysForm(item, si);
|
||||
if (item.IsString())
|
||||
si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue;
|
||||
si.dwTypeData = item.StringValue.Ptr_non_const();
|
||||
return SetItemInfo(itemIndex, byPosition, &si);
|
||||
}
|
||||
}
|
||||
@@ -171,7 +175,7 @@ bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
|
||||
if (item.IsString())
|
||||
{
|
||||
s = GetSystemString(item.StringValue);
|
||||
si.dwTypeData = (LPTSTR)(LPCTSTR)s;
|
||||
si.dwTypeData = s.Ptr_non_const();
|
||||
}
|
||||
return InsertItem(itemIndex, byPosition, &si);
|
||||
}
|
||||
@@ -181,7 +185,7 @@ bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
|
||||
MENUITEMINFOW si;
|
||||
ConvertItemToSysForm(item, si);
|
||||
if (item.IsString())
|
||||
si.dwTypeData = (LPWSTR)(LPCWSTR)item.StringValue;
|
||||
si.dwTypeData = item.StringValue.Ptr_non_const();
|
||||
#ifdef UNDER_CE
|
||||
UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING;
|
||||
UINT id = item.wID;
|
||||
|
||||
@@ -35,11 +35,11 @@ DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, LPNETRESOURCEW netResour
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srsString)
|
||||
static void SetComplexString(bool &defined, CSysString &destString, LPCTSTR srcString)
|
||||
{
|
||||
defined = (srsString != 0);
|
||||
defined = (srcString != 0);
|
||||
if (defined)
|
||||
destString = srsString;
|
||||
destString = srcString;
|
||||
else
|
||||
destString.Empty();
|
||||
}
|
||||
@@ -59,9 +59,9 @@ static void ConvertNETRESOURCEToCResource(const NETRESOURCE &netResource, CResou
|
||||
static void SetComplexString2(LPTSTR *destString, bool defined, const CSysString &srcString)
|
||||
{
|
||||
if (defined)
|
||||
*destString = (TCHAR *)(const TCHAR *)srcString;
|
||||
*destString = srcString.Ptr_non_const();
|
||||
else
|
||||
*destString = 0;
|
||||
*destString = NULL;
|
||||
}
|
||||
|
||||
static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE &netResource)
|
||||
@@ -78,11 +78,11 @@ static void ConvertCResourceToNETRESOURCE(const CResource &resource, NETRESOURCE
|
||||
|
||||
#ifndef _UNICODE
|
||||
|
||||
static void SetComplexString(bool &defined, UString &destString, LPCWSTR srsString)
|
||||
static void SetComplexString(bool &defined, UString &destString, LPCWSTR src)
|
||||
{
|
||||
defined = (srsString != 0);
|
||||
defined = (src != NULL);
|
||||
if (defined)
|
||||
destString = srsString;
|
||||
destString = src;
|
||||
else
|
||||
destString.Empty();
|
||||
}
|
||||
@@ -102,9 +102,9 @@ static void ConvertNETRESOURCEToCResource(const NETRESOURCEW &netResource, CReso
|
||||
static void SetComplexString2(LPWSTR *destString, bool defined, const UString &srcString)
|
||||
{
|
||||
if (defined)
|
||||
*destString = (WCHAR *)(const WCHAR *)srcString;
|
||||
*destString = srcString.Ptr_non_const();
|
||||
else
|
||||
*destString = 0;
|
||||
*destString = NULL;
|
||||
}
|
||||
|
||||
static void ConvertCResourceToNETRESOURCE(const CResourceW &resource, NETRESOURCEW &netResource)
|
||||
@@ -141,10 +141,8 @@ static void ConvertResourceToResourceW(const CResource &resource, CResourceW &re
|
||||
DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResource *resource)
|
||||
{
|
||||
NETRESOURCE netResource;
|
||||
LPNETRESOURCE pointer;
|
||||
if (resource == 0)
|
||||
pointer = 0;
|
||||
else
|
||||
LPNETRESOURCE pointer = NULL;
|
||||
if (resource)
|
||||
{
|
||||
ConvertCResourceToNETRESOURCE(*resource, netResource);
|
||||
pointer = &netResource;
|
||||
@@ -158,21 +156,17 @@ DWORD CEnum::Open(DWORD scope, DWORD type, DWORD usage, const CResourceW *resour
|
||||
if (g_IsNT)
|
||||
{
|
||||
NETRESOURCEW netResource;
|
||||
LPNETRESOURCEW pointer;
|
||||
if (resource == 0)
|
||||
pointer = 0;
|
||||
else
|
||||
LPNETRESOURCEW pointer = NULL;
|
||||
if (resource)
|
||||
{
|
||||
ConvertCResourceToNETRESOURCE(*resource, netResource);
|
||||
pointer = &netResource;
|
||||
}
|
||||
return Open(scope, type, usage, pointer);
|
||||
}
|
||||
CResource *pointer;
|
||||
CResource resourceA;
|
||||
if (resource == 0)
|
||||
pointer = 0;
|
||||
else
|
||||
CResource *pointer = NULL;
|
||||
if (resource)
|
||||
{
|
||||
ConvertResourceWToResource(*resource, resourceA);
|
||||
pointer = &resourceA;
|
||||
@@ -206,7 +200,7 @@ DWORD CEnum::Next(CResource &resource)
|
||||
{
|
||||
const DWORD kBufferSize = 16384;
|
||||
CByteArr byteBuffer(kBufferSize);
|
||||
LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer);
|
||||
LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer);
|
||||
ZeroMemory(lpnrLocal, kBufferSize);
|
||||
DWORD bufferSize = kBufferSize;
|
||||
DWORD numEntries = 1;
|
||||
@@ -226,7 +220,7 @@ DWORD CEnum::Next(CResourceW &resource)
|
||||
{
|
||||
const DWORD kBufferSize = 16384;
|
||||
CByteArr byteBuffer(kBufferSize);
|
||||
LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer);
|
||||
LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer);
|
||||
ZeroMemory(lpnrLocal, kBufferSize);
|
||||
DWORD bufferSize = kBufferSize;
|
||||
DWORD numEntries = 1;
|
||||
@@ -250,7 +244,7 @@ DWORD GetResourceParent(const CResource &resource, CResource &parentResource)
|
||||
{
|
||||
const DWORD kBufferSize = 16384;
|
||||
CByteArr byteBuffer(kBufferSize);
|
||||
LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer);
|
||||
LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer);
|
||||
ZeroMemory(lpnrLocal, kBufferSize);
|
||||
DWORD bufferSize = kBufferSize;
|
||||
NETRESOURCE netResource;
|
||||
@@ -269,7 +263,7 @@ DWORD GetResourceParent(const CResourceW &resource, CResourceW &parentResource)
|
||||
{
|
||||
const DWORD kBufferSize = 16384;
|
||||
CByteArr byteBuffer(kBufferSize);
|
||||
LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer);
|
||||
LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer);
|
||||
ZeroMemory(lpnrLocal, kBufferSize);
|
||||
DWORD bufferSize = kBufferSize;
|
||||
NETRESOURCEW netResource;
|
||||
@@ -293,7 +287,7 @@ DWORD GetResourceInformation(const CResource &resource,
|
||||
{
|
||||
const DWORD kBufferSize = 16384;
|
||||
CByteArr byteBuffer(kBufferSize);
|
||||
LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (BYTE *)(byteBuffer);
|
||||
LPNETRESOURCE lpnrLocal = (LPNETRESOURCE) (void *) (BYTE *)(byteBuffer);
|
||||
ZeroMemory(lpnrLocal, kBufferSize);
|
||||
DWORD bufferSize = kBufferSize;
|
||||
NETRESOURCE netResource;
|
||||
@@ -317,7 +311,7 @@ DWORD GetResourceInformation(const CResourceW &resource,
|
||||
{
|
||||
const DWORD kBufferSize = 16384;
|
||||
CByteArr byteBuffer(kBufferSize);
|
||||
LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (BYTE *)(byteBuffer);
|
||||
LPNETRESOURCEW lpnrLocal = (LPNETRESOURCEW) (void *) (BYTE *)(byteBuffer);
|
||||
ZeroMemory(lpnrLocal, kBufferSize);
|
||||
DWORD bufferSize = kBufferSize;
|
||||
NETRESOURCEW netResource;
|
||||
|
||||
@@ -17,6 +17,8 @@ static inline bool IsItWindowsNT()
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
extern
|
||||
bool g_IsNT;
|
||||
#if defined(_WIN64) || defined(UNDER_CE)
|
||||
bool g_IsNT = true;
|
||||
#define SET_IS_NT
|
||||
|
||||
@@ -24,6 +24,21 @@ static UString GetQuotedString(const UString &s)
|
||||
|
||||
WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir)
|
||||
{
|
||||
/*
|
||||
OutputDebugStringW(L"CProcess::Create");
|
||||
OutputDebugStringW(imageName);
|
||||
if (params)
|
||||
{
|
||||
OutputDebugStringW(L"params:");
|
||||
OutputDebugStringW(params);
|
||||
}
|
||||
if (curDir)
|
||||
{
|
||||
OutputDebugStringW(L"cur dir:");
|
||||
OutputDebugStringW(curDir);
|
||||
}
|
||||
*/
|
||||
|
||||
Close();
|
||||
const UString params2 =
|
||||
#ifndef UNDER_CE
|
||||
@@ -52,7 +67,8 @@ WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir)
|
||||
CSysString curDirA;
|
||||
if (curDir != 0)
|
||||
curDirA = GetSystemString(curDir);
|
||||
result = ::CreateProcessA(NULL, (LPSTR)(LPCSTR)GetSystemString(params2),
|
||||
const AString s = GetSystemString(params2);
|
||||
result = ::CreateProcessA(NULL, s.Ptr_non_const(),
|
||||
NULL, NULL, FALSE, 0, NULL, ((curDir != 0) ? (LPCSTR)curDirA: 0), &si, &pi);
|
||||
}
|
||||
else
|
||||
@@ -67,8 +83,8 @@ WRes CProcess::Create(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir)
|
||||
si.cbReserved2 = 0;
|
||||
si.lpReserved2 = 0;
|
||||
|
||||
result = CreateProcessW(imageName, (LPWSTR)(LPCWSTR)params2,
|
||||
NULL, NULL, FALSE, 0, NULL, (LPWSTR)curDir, &si, &pi);
|
||||
result = CreateProcessW(imageName, params2.Ptr_non_const(),
|
||||
NULL, NULL, FALSE, 0, NULL, curDir, &si, &pi);
|
||||
}
|
||||
if (result == 0)
|
||||
return ::GetLastError();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifndef __WINDOWS_PROCESS_UTILS_H
|
||||
#define __WINDOWS_PROCESS_UTILS_H
|
||||
|
||||
#include <psapi.h>
|
||||
#include <Psapi.h>
|
||||
|
||||
#include "../Common/MyString.h"
|
||||
|
||||
|
||||
@@ -278,7 +278,8 @@ HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
|
||||
HRESULT hr = Clear();
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
memcpy(this, pSrc, sizeof(PROPVARIANT));
|
||||
// memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));
|
||||
*(PROPVARIANT *)this = *pSrc;
|
||||
pSrc->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -291,7 +292,8 @@ HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
memcpy(pDest, this, sizeof(PROPVARIANT));
|
||||
// memcpy(pDest, this, sizeof(PROPVARIANT));
|
||||
*pDest = *(PROPVARIANT *)this;
|
||||
vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// PropVariantConvert.cpp
|
||||
// PropVariantConv.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -86,7 +86,7 @@ bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) th
|
||||
bool res = ConvertUtcFileTimeToString(ft, s, level);
|
||||
for (unsigned i = 0;; i++)
|
||||
{
|
||||
unsigned char c = s[i];
|
||||
Byte c = (Byte)s[i];
|
||||
dest[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
@@ -128,7 +128,7 @@ void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM
|
||||
}
|
||||
|
||||
|
||||
AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags)
|
||||
static AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags)
|
||||
{
|
||||
AString s;
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
|
||||
@@ -119,7 +119,7 @@ LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw()
|
||||
{
|
||||
MYASSERT(_object != NULL);
|
||||
return RegSetValueEx(_object, name, 0, REG_DWORD,
|
||||
(BYTE * const)&value, sizeof(UInt32));
|
||||
(const BYTE *)&value, sizeof(UInt32));
|
||||
}
|
||||
|
||||
LONG CKey::SetValue(LPCTSTR name, bool value) throw()
|
||||
@@ -132,7 +132,7 @@ LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw()
|
||||
MYASSERT(value != NULL);
|
||||
MYASSERT(_object != NULL);
|
||||
return RegSetValueEx(_object, name, 0, REG_SZ,
|
||||
(const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR));
|
||||
(const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -193,7 +193,7 @@ LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw()
|
||||
{
|
||||
DWORD type = 0;
|
||||
DWORD count = sizeof(DWORD);
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type,
|
||||
LONG res = RegQueryValueEx(_object, name, NULL, &type,
|
||||
(LPBYTE)&value, &count);
|
||||
MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD));
|
||||
MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32)));
|
||||
@@ -219,7 +219,7 @@ LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw()
|
||||
|
||||
LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()
|
||||
{
|
||||
bool newVal;
|
||||
bool newVal = false;
|
||||
LONG res = QueryValue(name, newVal);
|
||||
if (res == ERROR_SUCCESS)
|
||||
value = newVal;
|
||||
@@ -229,7 +229,7 @@ LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()
|
||||
LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()
|
||||
{
|
||||
DWORD type = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
|
||||
LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
|
||||
MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
|
||||
return res;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
|
||||
value.Empty();
|
||||
DWORD type = 0;
|
||||
UInt32 curSize = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize);
|
||||
LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&curSize);
|
||||
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
|
||||
return res;
|
||||
UInt32 curSize2 = curSize;
|
||||
@@ -296,7 +296,7 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value)
|
||||
LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()
|
||||
{
|
||||
DWORD type = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
|
||||
LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
|
||||
MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY));
|
||||
return res;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)
|
||||
{
|
||||
DWORD type = 0;
|
||||
dataSize = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize);
|
||||
LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize);
|
||||
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
|
||||
return res;
|
||||
value.Alloc(dataSize);
|
||||
@@ -369,7 +369,7 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
|
||||
if (dataSize % sizeof(wchar_t) != 0)
|
||||
return E_FAIL;
|
||||
|
||||
const wchar_t *data = (const wchar_t *)(const Byte *)buffer;
|
||||
const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer;
|
||||
size_t numChars = dataSize / sizeof(wchar_t);
|
||||
size_t prev = 0;
|
||||
UString s;
|
||||
|
||||
@@ -25,10 +25,10 @@ static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID)
|
||||
do
|
||||
{
|
||||
size <<= 1;
|
||||
len = ::LoadString(hInstance, resourceID, s.GetBuf(size - 1), size);
|
||||
len = ::LoadString(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size);
|
||||
}
|
||||
while (size - len <= 1);
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
s.ReleaseBuf_CalcLen((unsigned)len);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s)
|
||||
do
|
||||
{
|
||||
size <<= 1;
|
||||
len = ::LoadStringW(hInstance, resourceID, s.GetBuf(size - 1), size);
|
||||
len = ::LoadStringW(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size);
|
||||
}
|
||||
while (size - len <= 1);
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
s.ReleaseBuf_CalcLen((unsigned)len);
|
||||
}
|
||||
|
||||
// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.
|
||||
|
||||
@@ -34,7 +34,7 @@ bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,
|
||||
|
||||
static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest)
|
||||
{
|
||||
int len = (int)wcslen(src);
|
||||
size_t len = (size_t)wcslen(src);
|
||||
dest->Length = (USHORT)(len * sizeof(WCHAR));
|
||||
dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));
|
||||
dest->Buffer = src;
|
||||
|
||||
@@ -192,7 +192,7 @@ bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
|
||||
}
|
||||
|
||||
|
||||
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
|
||||
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
|
||||
{
|
||||
#ifndef UNDER_CE
|
||||
switch (uMsg)
|
||||
@@ -221,7 +221,7 @@ int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM da
|
||||
}
|
||||
|
||||
|
||||
bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
|
||||
static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
|
||||
LPCTSTR initialFolder, CSysString &resultPath)
|
||||
{
|
||||
CSysString displayName;
|
||||
@@ -275,7 +275,7 @@ bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
|
||||
|
||||
typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
|
||||
|
||||
bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
|
||||
static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
|
||||
{
|
||||
NWindows::NCOM::CComInitializer comInitializer;
|
||||
SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
|
||||
@@ -290,7 +290,7 @@ bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
|
||||
return GetPathFromIDList(itemIDList, resultPath);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
|
||||
{
|
||||
switch (uMsg)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#ifndef __WINDOWS_SHELL_H
|
||||
#define __WINDOWS_SHELL_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include "../Common/MyWindows.h"
|
||||
#include <ShlObj.h>
|
||||
|
||||
#include "../Common/MyString.h"
|
||||
|
||||
|
||||
@@ -2,9 +2,62 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "Synchronization.h"
|
||||
|
||||
namespace NWindows {
|
||||
namespace NSynchronization {
|
||||
|
||||
/*
|
||||
#define INFINITE 0xFFFFFFFF
|
||||
#define MAXIMUM_WAIT_OBJECTS 64
|
||||
#define STATUS_ABANDONED_WAIT_0 ((NTSTATUS)0x00000080L)
|
||||
#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
||||
#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
||||
// WINAPI
|
||||
DWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout);
|
||||
*/
|
||||
|
||||
DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)
|
||||
{
|
||||
if (count < 1)
|
||||
{
|
||||
// abort();
|
||||
SetLastError(EINVAL);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
CSynchro *synchro = handles[0]->_sync;
|
||||
synchro->Enter();
|
||||
|
||||
// #ifdef DEBUG_SYNCHRO
|
||||
for (DWORD i = 1; i < count; i++)
|
||||
{
|
||||
if (synchro != handles[i]->_sync)
|
||||
{
|
||||
// abort();
|
||||
synchro->Leave();
|
||||
SetLastError(EINVAL);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (DWORD i = 0; i < count; i++)
|
||||
{
|
||||
if (handles[i]->IsSignaledAndUpdate())
|
||||
{
|
||||
synchro->Leave();
|
||||
return WAIT_OBJECT_0 + i;
|
||||
}
|
||||
}
|
||||
synchro->WaitCond();
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "../../C/Threads.h"
|
||||
|
||||
#include "../Common/MyTypes.h"
|
||||
|
||||
#include "Defs.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -14,17 +16,19 @@
|
||||
namespace NWindows {
|
||||
namespace NSynchronization {
|
||||
|
||||
class CBaseEvent
|
||||
class CBaseEvent MY_UNCOPYABLE
|
||||
{
|
||||
protected:
|
||||
::CEvent _object;
|
||||
public:
|
||||
bool IsCreated() { return Event_IsCreated(&_object) != 0; }
|
||||
operator HANDLE() { return _object; }
|
||||
|
||||
CBaseEvent() { Event_Construct(&_object); }
|
||||
~CBaseEvent() { Close(); }
|
||||
WRes Close() { return Event_Close(&_object); }
|
||||
|
||||
#ifdef _WIN32
|
||||
operator HANDLE() { return _object; }
|
||||
WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)
|
||||
{
|
||||
_object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name);
|
||||
@@ -54,10 +58,10 @@ public:
|
||||
{
|
||||
return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);
|
||||
}
|
||||
WRes CreateIfNotCreated()
|
||||
WRes CreateIfNotCreated_Reset()
|
||||
{
|
||||
if (IsCreated())
|
||||
return 0;
|
||||
return Reset();
|
||||
return ManualResetEvent_CreateNotSignaled(&_object);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
@@ -75,21 +79,25 @@ public:
|
||||
{
|
||||
return AutoResetEvent_CreateNotSignaled(&_object);
|
||||
}
|
||||
WRes CreateIfNotCreated()
|
||||
WRes CreateIfNotCreated_Reset()
|
||||
{
|
||||
if (IsCreated())
|
||||
return 0;
|
||||
return Reset();
|
||||
return AutoResetEvent_CreateNotSignaled(&_object);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
#ifdef _WIN32
|
||||
|
||||
class CObject: public CHandle
|
||||
{
|
||||
public:
|
||||
WRes Lock(DWORD timeoutInterval = INFINITE)
|
||||
{ return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }
|
||||
};
|
||||
|
||||
class CMutex: public CObject
|
||||
{
|
||||
public:
|
||||
@@ -114,33 +122,43 @@ public:
|
||||
return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();
|
||||
}
|
||||
};
|
||||
class CMutexLock
|
||||
|
||||
class CMutexLock MY_UNCOPYABLE
|
||||
{
|
||||
CMutex *_object;
|
||||
public:
|
||||
CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }
|
||||
~CMutexLock() { _object->Release(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
class CSemaphore
|
||||
#endif // _WIN32
|
||||
*/
|
||||
|
||||
|
||||
class CSemaphore MY_UNCOPYABLE
|
||||
{
|
||||
::CSemaphore _object;
|
||||
public:
|
||||
CSemaphore() { Semaphore_Construct(&_object); }
|
||||
~CSemaphore() { Close(); }
|
||||
WRes Close() { return Semaphore_Close(&_object); }
|
||||
WRes Close() { return Semaphore_Close(&_object); }
|
||||
|
||||
#ifdef _WIN32
|
||||
operator HANDLE() { return _object; }
|
||||
WRes Create(UInt32 initiallyCount, UInt32 maxCount)
|
||||
#endif
|
||||
|
||||
// bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; }
|
||||
|
||||
WRes Create(UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
return Semaphore_Create(&_object, initiallyCount, maxCount);
|
||||
return Semaphore_Create(&_object, initCount, maxCount);
|
||||
}
|
||||
WRes Release() { return Semaphore_Release1(&_object); }
|
||||
WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }
|
||||
WRes Lock() { return Semaphore_Wait(&_object); }
|
||||
};
|
||||
|
||||
class CCriticalSection
|
||||
class CCriticalSection MY_UNCOPYABLE
|
||||
{
|
||||
::CCriticalSection _object;
|
||||
public:
|
||||
@@ -150,7 +168,7 @@ public:
|
||||
void Leave() { CriticalSection_Leave(&_object); }
|
||||
};
|
||||
|
||||
class CCriticalSectionLock
|
||||
class CCriticalSectionLock MY_UNCOPYABLE
|
||||
{
|
||||
CCriticalSection *_object;
|
||||
void Unlock() { _object->Leave(); }
|
||||
@@ -159,6 +177,213 @@ public:
|
||||
~CCriticalSectionLock() { Unlock(); }
|
||||
};
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef HANDLE CHandle_WFMO;
|
||||
typedef CSemaphore CSemaphore_WFMO;
|
||||
typedef CAutoResetEvent CAutoResetEvent_WFMO;
|
||||
typedef CManualResetEvent CManualResetEvent_WFMO;
|
||||
|
||||
inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)
|
||||
{
|
||||
return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);
|
||||
}
|
||||
|
||||
#define SYNC_OBJ_DECL(obj)
|
||||
#define SYNC_WFMO(x)
|
||||
#define SYNC_PARAM(x)
|
||||
#define SYNC_PARAM_DECL(x)
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// POSIX sync objects for WaitForMultipleObjects
|
||||
|
||||
#define SYNC_WFMO(x) x
|
||||
#define SYNC_PARAM(x) x,
|
||||
#define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x
|
||||
#define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x;
|
||||
|
||||
class CSynchro MY_UNCOPYABLE
|
||||
{
|
||||
pthread_mutex_t _mutex;
|
||||
pthread_cond_t _cond;
|
||||
bool _isValid;
|
||||
|
||||
public:
|
||||
CSynchro() { _isValid = false; }
|
||||
~CSynchro()
|
||||
{
|
||||
if (_isValid)
|
||||
{
|
||||
::pthread_mutex_destroy(&_mutex);
|
||||
::pthread_cond_destroy(&_cond);
|
||||
}
|
||||
_isValid = false;
|
||||
}
|
||||
WRes Create()
|
||||
{
|
||||
RINOK(::pthread_mutex_init(&_mutex, 0));
|
||||
WRes ret = ::pthread_cond_init(&_cond, 0);
|
||||
_isValid = 1;
|
||||
return ret;
|
||||
}
|
||||
WRes Enter()
|
||||
{
|
||||
return ::pthread_mutex_lock(&_mutex);
|
||||
}
|
||||
WRes Leave()
|
||||
{
|
||||
return ::pthread_mutex_unlock(&_mutex);
|
||||
}
|
||||
WRes WaitCond()
|
||||
{
|
||||
return ::pthread_cond_wait(&_cond, &_mutex);
|
||||
}
|
||||
WRes LeaveAndSignal()
|
||||
{
|
||||
WRes res1 = ::pthread_cond_broadcast(&_cond);
|
||||
WRes res2 = ::pthread_mutex_unlock(&_mutex);
|
||||
return (res2 ? res2 : res1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CBaseHandle_WFMO;
|
||||
typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO;
|
||||
|
||||
// these constants are from Windows
|
||||
#define WAIT_OBJECT_0 0
|
||||
#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
|
||||
|
||||
DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles);
|
||||
|
||||
|
||||
struct CBaseHandle_WFMO MY_UNCOPYABLE
|
||||
{
|
||||
CSynchro *_sync;
|
||||
|
||||
CBaseHandle_WFMO(): _sync(NULL) {}
|
||||
|
||||
operator CHandle_WFMO() { return this; }
|
||||
virtual bool IsSignaledAndUpdate() = 0;
|
||||
};
|
||||
|
||||
|
||||
class CBaseEvent_WFMO : public CBaseHandle_WFMO
|
||||
{
|
||||
bool _manual_reset;
|
||||
bool _state;
|
||||
|
||||
public:
|
||||
|
||||
// bool IsCreated() { return (this->_sync != NULL); }
|
||||
// CBaseEvent_WFMO() { ; }
|
||||
~CBaseEvent_WFMO() { Close(); }
|
||||
|
||||
WRes Close() { this->_sync = NULL; return 0; }
|
||||
|
||||
WRes Create(
|
||||
CSynchro *sync,
|
||||
bool manualReset, bool initiallyOwn)
|
||||
{
|
||||
this->_sync = sync;
|
||||
this->_manual_reset = manualReset;
|
||||
this->_state = initiallyOwn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes Set()
|
||||
{
|
||||
RINOK(this->_sync->Enter());
|
||||
this->_state = true;
|
||||
return this->_sync->LeaveAndSignal();
|
||||
}
|
||||
|
||||
WRes Reset()
|
||||
{
|
||||
RINOK(this->_sync->Enter());
|
||||
this->_state = false;
|
||||
return this->_sync->Leave();
|
||||
}
|
||||
|
||||
virtual bool IsSignaledAndUpdate()
|
||||
{
|
||||
if (this->_state == false)
|
||||
return false;
|
||||
if (this->_manual_reset == false)
|
||||
this->_state = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CManualResetEvent_WFMO: public CBaseEvent_WFMO
|
||||
{
|
||||
public:
|
||||
WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); }
|
||||
};
|
||||
|
||||
|
||||
class CAutoResetEvent_WFMO: public CBaseEvent_WFMO
|
||||
{
|
||||
public:
|
||||
WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); }
|
||||
WRes CreateIfNotCreated_Reset(CSynchro *sync)
|
||||
{
|
||||
return Create(sync);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CSemaphore_WFMO : public CBaseHandle_WFMO
|
||||
{
|
||||
UInt32 _count;
|
||||
UInt32 _maxCount;
|
||||
|
||||
public:
|
||||
CSemaphore_WFMO() : _count(0), _maxCount(0) {}
|
||||
|
||||
WRes Close() { this->_sync = NULL; return 0; }
|
||||
|
||||
WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
if (initCount > maxCount || maxCount < 1)
|
||||
return EINVAL;
|
||||
this->_sync = sync;
|
||||
this->_count = initCount;
|
||||
this->_maxCount = maxCount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes Release(UInt32 releaseCount = 1)
|
||||
{
|
||||
if (releaseCount < 1)
|
||||
return EINVAL;
|
||||
|
||||
RINOK(this->_sync->Enter());
|
||||
UInt32 newCount = this->_count + releaseCount;
|
||||
if (newCount > this->_maxCount)
|
||||
{
|
||||
RINOK(this->_sync->Leave());
|
||||
return ERROR_TOO_MANY_POSTS; // EINVAL
|
||||
}
|
||||
this->_count = newCount;
|
||||
|
||||
return this->_sync->LeaveAndSignal();
|
||||
}
|
||||
|
||||
virtual bool IsSignaledAndUpdate()
|
||||
{
|
||||
if (this->_count == 0)
|
||||
return false;
|
||||
this->_count--;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,15 +2,27 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../Common/MyWindows.h"
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
#else
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../Common/Defs.h"
|
||||
// #include "../Common/MyWindows.h"
|
||||
|
||||
// #include "../../C/CpuArch.h"
|
||||
|
||||
#include "System.h"
|
||||
|
||||
namespace NWindows {
|
||||
namespace NSystem {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
UInt32 CountAffinity(DWORD_PTR mask)
|
||||
{
|
||||
UInt32 num = 0;
|
||||
@@ -19,8 +31,6 @@ UInt32 CountAffinity(DWORD_PTR mask)
|
||||
return num;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
BOOL CProcessAffinity::Get()
|
||||
{
|
||||
#ifndef UNDER_CE
|
||||
@@ -52,9 +62,45 @@ UInt32 GetNumberOfProcessors()
|
||||
|
||||
#else
|
||||
|
||||
|
||||
BOOL CProcessAffinity::Get()
|
||||
{
|
||||
numSysThreads = GetNumberOfProcessors();
|
||||
|
||||
/*
|
||||
numSysThreads = 8;
|
||||
for (unsigned i = 0; i < numSysThreads; i++)
|
||||
CpuSet_Set(&cpu_set, i);
|
||||
return TRUE;
|
||||
*/
|
||||
|
||||
#ifdef _7ZIP_AFFINITY_SUPPORTED
|
||||
|
||||
// numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online
|
||||
if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
||||
#else
|
||||
|
||||
// cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1;
|
||||
return TRUE;
|
||||
// errno = ENOSYS;
|
||||
// return FALSE;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt32 GetNumberOfProcessors()
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
long n = sysconf(_SC_NPROCESSORS_CONF); // The number of processors configured
|
||||
if (n < 1)
|
||||
n = 1;
|
||||
return (UInt32)n;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -87,17 +133,13 @@ typedef struct _MY_MEMORYSTATUSEX {
|
||||
|
||||
typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !UNDER_CE
|
||||
|
||||
|
||||
bool GetRamSize(UInt64 &size)
|
||||
{
|
||||
size = (UInt64)(sizeof(size_t)) << 29;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef UNDER_CE
|
||||
MY_MEMORYSTATUSEX stat;
|
||||
stat.dwLength = sizeof(stat);
|
||||
@@ -114,7 +156,7 @@ bool GetRamSize(UInt64 &size)
|
||||
|
||||
#ifndef UNDER_CE
|
||||
GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)
|
||||
::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx");
|
||||
(void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GlobalMemoryStatusEx");
|
||||
if (globalMemoryStatusEx && globalMemoryStatusEx(&stat))
|
||||
{
|
||||
size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);
|
||||
@@ -129,14 +171,61 @@ bool GetRamSize(UInt64 &size)
|
||||
size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// POSIX
|
||||
// #include <stdio.h>
|
||||
|
||||
bool GetRamSize(UInt64 &size)
|
||||
{
|
||||
size = (UInt64)(sizeof(size_t)) << 29;
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#ifdef HW_MEMSIZE
|
||||
uint64_t val = 0; // support 2Gb+ RAM
|
||||
int mib[2] = { CTL_HW, HW_MEMSIZE };
|
||||
#elif defined(HW_PHYSMEM64)
|
||||
uint64_t val = 0; // support 2Gb+ RAM
|
||||
int mib[2] = { CTL_HW, HW_PHYSMEM64 };
|
||||
#else
|
||||
unsigned int val = 0; // For old system
|
||||
int mib[2] = { CTL_HW, HW_PHYSMEM };
|
||||
#endif // HW_MEMSIZE
|
||||
size_t size_sys = sizeof(val);
|
||||
|
||||
sysctl(mib, 2, &val, &size_sys, NULL, 0);
|
||||
if (val)
|
||||
size = val;
|
||||
|
||||
#elif defined(_AIX)
|
||||
|
||||
// fixme
|
||||
|
||||
#else
|
||||
|
||||
return false;
|
||||
struct sysinfo info;
|
||||
if (::sysinfo(&info) != 0)
|
||||
return false;
|
||||
size = (UInt64)info.mem_unit * info.totalram;
|
||||
const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1);
|
||||
if (size > kLimit)
|
||||
size = kLimit;
|
||||
|
||||
/*
|
||||
printf("\n mem_unit = %lld", (UInt64)info.mem_unit);
|
||||
printf("\n totalram = %lld", (UInt64)info.totalram);
|
||||
printf("\n freeram = %lld", (UInt64)info.freeram);
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,11 +3,19 @@
|
||||
#ifndef __WINDOWS_SYSTEM_H
|
||||
#define __WINDOWS_SYSTEM_H
|
||||
|
||||
#ifndef _WIN32
|
||||
// #include <sched.h>
|
||||
#include "../../C/Threads.h"
|
||||
#endif
|
||||
|
||||
#include "../Common/MyTypes.h"
|
||||
|
||||
namespace NWindows {
|
||||
namespace NSystem {
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
UInt32 CountAffinity(DWORD_PTR mask);
|
||||
|
||||
struct CProcessAffinity
|
||||
@@ -25,12 +33,93 @@ struct CProcessAffinity
|
||||
systemAffinityMask = 1;
|
||||
}
|
||||
|
||||
void CpuZero()
|
||||
{
|
||||
processAffinityMask = 0;
|
||||
}
|
||||
|
||||
void CpuSet(unsigned cpuIndex)
|
||||
{
|
||||
processAffinityMask |= ((DWORD_PTR)1 << cpuIndex);
|
||||
}
|
||||
|
||||
UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); }
|
||||
UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); }
|
||||
|
||||
BOOL Get();
|
||||
|
||||
BOOL SetProcAffinity() const
|
||||
{
|
||||
return SetProcessAffinityMask(GetCurrentProcess(), processAffinityMask);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#else // WIN32
|
||||
|
||||
struct CProcessAffinity
|
||||
{
|
||||
UInt32 numSysThreads;
|
||||
|
||||
UInt32 GetNumSystemThreads() const { return (UInt32)numSysThreads; }
|
||||
BOOL Get();
|
||||
|
||||
#ifdef _7ZIP_AFFINITY_SUPPORTED
|
||||
|
||||
CCpuSet cpu_set;
|
||||
|
||||
void InitST()
|
||||
{
|
||||
numSysThreads = 1;
|
||||
CpuSet_Zero(&cpu_set);
|
||||
CpuSet_Set(&cpu_set, 0);
|
||||
}
|
||||
|
||||
UInt32 GetNumProcessThreads() const { return (UInt32)CPU_COUNT(&cpu_set); }
|
||||
void CpuZero() { CpuSet_Zero(&cpu_set); }
|
||||
void CpuSet(unsigned cpuIndex) { CpuSet_Set(&cpu_set, cpuIndex); }
|
||||
int IsCpuSet(unsigned cpuIndex) const { return CpuSet_IsSet(&cpu_set, cpuIndex); }
|
||||
// void CpuClr(int cpuIndex) { CPU_CLR(cpuIndex, &cpu_set); }
|
||||
|
||||
BOOL SetProcAffinity() const
|
||||
{
|
||||
return sched_setaffinity(0, sizeof(cpu_set), &cpu_set) == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void InitST()
|
||||
{
|
||||
numSysThreads = 1;
|
||||
}
|
||||
|
||||
UInt32 GetNumProcessThreads() const
|
||||
{
|
||||
return numSysThreads;
|
||||
/*
|
||||
UInt32 num = 0;
|
||||
for (unsigned i = 0; i < sizeof(cpu_set) * 8; i++)
|
||||
num += (UInt32)((cpu_set >> i) & 1);
|
||||
return num;
|
||||
*/
|
||||
}
|
||||
|
||||
void CpuZero() { }
|
||||
void CpuSet(unsigned cpuIndex) { UNUSED_VAR(cpuIndex); }
|
||||
int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; }
|
||||
|
||||
BOOL SetProcAffinity() const
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
UInt32 GetNumberOfProcessors();
|
||||
|
||||
bool GetRamSize(UInt64 &size); // returns false, if unknown ram size
|
||||
|
||||
716
CPP/Windows/SystemInfo.cpp
Normal file
716
CPP/Windows/SystemInfo.cpp
Normal file
@@ -0,0 +1,716 @@
|
||||
// Windows/SystemInfo.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#include "../Common/IntToString.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Registry.h"
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
#elif !defined(_AIX)
|
||||
|
||||
|
||||
#include <sys/auxv.h>
|
||||
|
||||
#ifdef MY_CPU_ARM_OR_ARM64
|
||||
#include <asm/hwcap.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "SystemInfo.h"
|
||||
#include "System.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#ifndef __APPLE__
|
||||
static void PrintHex(AString &s, UInt64 v)
|
||||
{
|
||||
char temp[32];
|
||||
ConvertUInt64ToHex(v, temp);
|
||||
s += temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
static void PrintCpuChars(AString &s, UInt32 v)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
Byte b = (Byte)(v & 0xFF);
|
||||
v >>= 8;
|
||||
if (b == 0)
|
||||
break;
|
||||
s += (char)b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void x86cpuid_to_String(const Cx86cpuid &c, AString &s)
|
||||
{
|
||||
s.Empty();
|
||||
|
||||
UInt32 maxFunc2 = 0;
|
||||
UInt32 t[3];
|
||||
|
||||
MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]);
|
||||
|
||||
bool fullNameIsAvail = (maxFunc2 >= 0x80000004);
|
||||
|
||||
if (fullNameIsAvail)
|
||||
{
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]);
|
||||
for (unsigned j = 0; j < 4; j++)
|
||||
PrintCpuChars(s, d[j]);
|
||||
}
|
||||
}
|
||||
|
||||
s.Trim();
|
||||
|
||||
if (s.IsEmpty())
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
PrintCpuChars(s, c.vendor[i]);
|
||||
s.Trim();
|
||||
}
|
||||
|
||||
s.Add_Space_if_NotEmpty();
|
||||
{
|
||||
char temp[32];
|
||||
ConvertUInt32ToHex(c.ver, temp);
|
||||
s += '(';
|
||||
s += temp;
|
||||
s += ')';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void x86cpuid_all_to_String(AString &s)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return;
|
||||
s += "x86cpuid maxFunc = ";
|
||||
s.Add_UInt32(p.maxFunc);
|
||||
for (unsigned j = 0; j <= p.maxFunc; j++)
|
||||
{
|
||||
s.Add_LF();
|
||||
// s.Add_UInt32(j); // align
|
||||
{
|
||||
char temp[32];
|
||||
ConvertUInt32ToString(j, temp);
|
||||
unsigned len = (unsigned)strlen(temp);
|
||||
while (len < 8)
|
||||
{
|
||||
len++;
|
||||
s.Add_Space();
|
||||
}
|
||||
s += temp;
|
||||
}
|
||||
|
||||
s += ":";
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(j, &d[0], &d[1], &d[2], &d[3]);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
char temp[32];
|
||||
ConvertUInt32ToHex8Digits(d[i], temp);
|
||||
s += " ";
|
||||
s += temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static const char * const k_PROCESSOR_ARCHITECTURE[] =
|
||||
{
|
||||
"x86" // "INTEL"
|
||||
, "MIPS"
|
||||
, "ALPHA"
|
||||
, "PPC"
|
||||
, "SHX"
|
||||
, "ARM"
|
||||
, "IA64"
|
||||
, "ALPHA64"
|
||||
, "MSIL"
|
||||
, "x64" // "AMD64"
|
||||
, "IA32_ON_WIN64"
|
||||
, "NEUTRAL"
|
||||
, "ARM64"
|
||||
, "ARM32_ON_WIN64"
|
||||
};
|
||||
|
||||
#define MY__PROCESSOR_ARCHITECTURE_INTEL 0
|
||||
#define MY__PROCESSOR_ARCHITECTURE_AMD64 9
|
||||
|
||||
|
||||
#define MY__PROCESSOR_INTEL_PENTIUM 586
|
||||
#define MY__PROCESSOR_AMD_X8664 8664
|
||||
|
||||
/*
|
||||
static const CUInt32PCharPair k_PROCESSOR[] =
|
||||
{
|
||||
{ 2200, "IA64" },
|
||||
{ 8664, "x64" }
|
||||
};
|
||||
|
||||
#define PROCESSOR_INTEL_386 386
|
||||
#define PROCESSOR_INTEL_486 486
|
||||
#define PROCESSOR_INTEL_PENTIUM 586
|
||||
#define PROCESSOR_INTEL_860 860
|
||||
#define PROCESSOR_INTEL_IA64 2200
|
||||
#define PROCESSOR_AMD_X8664 8664
|
||||
#define PROCESSOR_MIPS_R2000 2000
|
||||
#define PROCESSOR_MIPS_R3000 3000
|
||||
#define PROCESSOR_MIPS_R4000 4000
|
||||
#define PROCESSOR_ALPHA_21064 21064
|
||||
#define PROCESSOR_PPC_601 601
|
||||
#define PROCESSOR_PPC_603 603
|
||||
#define PROCESSOR_PPC_604 604
|
||||
#define PROCESSOR_PPC_620 620
|
||||
#define PROCESSOR_HITACHI_SH3 10003
|
||||
#define PROCESSOR_HITACHI_SH3E 10004
|
||||
#define PROCESSOR_HITACHI_SH4 10005
|
||||
#define PROCESSOR_MOTOROLA_821 821
|
||||
#define PROCESSOR_SHx_SH3 103
|
||||
#define PROCESSOR_SHx_SH4 104
|
||||
#define PROCESSOR_STRONGARM 2577 // 0xA11
|
||||
#define PROCESSOR_ARM720 1824 // 0x720
|
||||
#define PROCESSOR_ARM820 2080 // 0x820
|
||||
#define PROCESSOR_ARM920 2336 // 0x920
|
||||
#define PROCESSOR_ARM_7TDMI 70001
|
||||
#define PROCESSOR_OPTIL 18767 // 0x494f
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
static const char * const k_PF[] =
|
||||
{
|
||||
"FP_ERRATA"
|
||||
, "FP_EMU"
|
||||
, "CMPXCHG"
|
||||
, "MMX"
|
||||
, "PPC_MOVEMEM_64BIT"
|
||||
, "ALPHA_BYTE"
|
||||
, "SSE"
|
||||
, "3DNOW"
|
||||
, "RDTSC"
|
||||
, "PAE"
|
||||
, "SSE2"
|
||||
, "SSE_DAZ"
|
||||
, "NX"
|
||||
, "SSE3"
|
||||
, "CMPXCHG16B"
|
||||
, "CMP8XCHG16"
|
||||
, "CHANNELS"
|
||||
, "XSAVE"
|
||||
, "ARM_VFP_32"
|
||||
, "ARM_NEON"
|
||||
, "L2AT"
|
||||
, "VIRT_FIRMWARE"
|
||||
, "RDWRFSGSBASE"
|
||||
, "FASTFAIL"
|
||||
, "ARM_DIVIDE"
|
||||
, "ARM_64BIT_LOADSTORE_ATOMIC"
|
||||
, "ARM_EXTERNAL_CACHE"
|
||||
, "ARM_FMAC"
|
||||
, "RDRAND"
|
||||
, "ARM_V8"
|
||||
, "ARM_V8_CRYPTO"
|
||||
, "ARM_V8_CRC32"
|
||||
, "RDTSCP"
|
||||
, "RDPID"
|
||||
, "ARM_V81_ATOMIC"
|
||||
, "MONITORX"
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static void PrintPage(AString &s, UInt32 v)
|
||||
{
|
||||
if ((v & 0x3FF) == 0)
|
||||
{
|
||||
s.Add_UInt32(v >> 10);
|
||||
s += "K";
|
||||
}
|
||||
else
|
||||
s.Add_UInt32(v >> 10);
|
||||
}
|
||||
|
||||
static AString TypeToString2(const char * const table[], unsigned num, UInt32 value)
|
||||
{
|
||||
char sz[16];
|
||||
const char *p = NULL;
|
||||
if (value < num)
|
||||
p = table[value];
|
||||
if (!p)
|
||||
{
|
||||
ConvertUInt32ToString(value, sz);
|
||||
p = sz;
|
||||
}
|
||||
return (AString)p;
|
||||
}
|
||||
|
||||
// #if defined(_7ZIP_LARGE_PAGES) || defined(_WIN32)
|
||||
// #ifdef _WIN32
|
||||
void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v)
|
||||
{
|
||||
char c = 0;
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'K';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'M';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'G';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'T';
|
||||
}}}}
|
||||
else
|
||||
{
|
||||
PrintHex(s, v);
|
||||
return;
|
||||
}
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(v, temp);
|
||||
s += temp;
|
||||
if (c)
|
||||
s += c;
|
||||
}
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
|
||||
{
|
||||
s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture);
|
||||
|
||||
if (!( (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM)
|
||||
|| (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664)))
|
||||
{
|
||||
s += " ";
|
||||
// s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType);
|
||||
s.Add_UInt32(si.dwProcessorType);
|
||||
}
|
||||
s += " ";
|
||||
PrintHex(s, si.wProcessorLevel);
|
||||
s += ".";
|
||||
PrintHex(s, si.wProcessorRevision);
|
||||
if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors))
|
||||
if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8)
|
||||
{
|
||||
s += " act:";
|
||||
PrintHex(s, si.dwActiveProcessorMask);
|
||||
}
|
||||
s += " cpus:";
|
||||
s.Add_UInt32(si.dwNumberOfProcessors);
|
||||
if (si.dwPageSize != 1 << 12)
|
||||
{
|
||||
s += " page:";
|
||||
PrintPage(s, si.dwPageSize);
|
||||
}
|
||||
if (si.dwAllocationGranularity != 1 << 16)
|
||||
{
|
||||
s += " gran:";
|
||||
PrintPage(s, si.dwAllocationGranularity);
|
||||
}
|
||||
s += " ";
|
||||
|
||||
DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress;
|
||||
UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1;
|
||||
const UInt32 kReserveSize = ((UInt32)1 << 16);
|
||||
if (minAdd != kReserveSize)
|
||||
{
|
||||
PrintSize_KMGT_Or_Hex(s, minAdd);
|
||||
s += "-";
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((maxSize & (kReserveSize - 1)) == 0)
|
||||
maxSize += kReserveSize;
|
||||
}
|
||||
PrintSize_KMGT_Or_Hex(s, maxSize);
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
EXTERN_C_BEGIN
|
||||
typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
|
||||
EXTERN_C_END
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef MY_CPU_X86_OR_AMD64
|
||||
static void Add_sysctlbyname_to_String(const char *name, AString &s)
|
||||
{
|
||||
size_t bufSize = 256;
|
||||
char buf[256];
|
||||
if (My_sysctlbyname_Get(name, &buf, &bufSize) == 0)
|
||||
s += buf;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void GetSysInfo(AString &s1, AString &s2);
|
||||
void GetSysInfo(AString &s1, AString &s2)
|
||||
{
|
||||
s1.Empty();
|
||||
s2.Empty();
|
||||
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
{
|
||||
SysInfo_To_String(s1, si);
|
||||
// s += " : ";
|
||||
}
|
||||
|
||||
#if !defined(_WIN64) && !defined(UNDER_CE)
|
||||
Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)(void *)GetProcAddress(
|
||||
GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
|
||||
if (fn_GetNativeSystemInfo)
|
||||
{
|
||||
SYSTEM_INFO si2;
|
||||
fn_GetNativeSystemInfo(&si2);
|
||||
// if (memcmp(&si, &si2, sizeof(si)) != 0)
|
||||
{
|
||||
// s += " - ";
|
||||
SysInfo_To_String(s2, si2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void GetCpuName(AString &s);
|
||||
void GetCpuName(AString &s)
|
||||
{
|
||||
s.Empty();
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
{
|
||||
Cx86cpuid cpuid;
|
||||
if (x86cpuid_CheckAndRead(&cpuid))
|
||||
{
|
||||
AString s2;
|
||||
x86cpuid_to_String(cpuid, s2);
|
||||
s += s2;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MY_CPU_AMD64
|
||||
s += "x64";
|
||||
#else
|
||||
s += "x86";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
{
|
||||
Add_sysctlbyname_to_String("machdep.cpu.brand_string", s);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (s.IsEmpty())
|
||||
{
|
||||
#ifdef MY_CPU_LE
|
||||
s += "LE";
|
||||
#elif defined(MY_CPU_BE)
|
||||
s += "BE";
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
{
|
||||
AString s2;
|
||||
UInt32 v = 0;
|
||||
if (My_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
|
||||
{
|
||||
s2.Add_UInt32(v);
|
||||
s2 += 'C';
|
||||
}
|
||||
if (My_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
|
||||
{
|
||||
s2.Add_UInt32(v);
|
||||
s2 += 'T';
|
||||
}
|
||||
if (!s2.IsEmpty())
|
||||
{
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += s2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
NRegistry::CKey key;
|
||||
if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
LONG res[2];
|
||||
CByteBuffer bufs[2];
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
UInt32 size = 0;
|
||||
res[i] = key.QueryValue(i == 0 ?
|
||||
TEXT("Previous Update Revision") :
|
||||
TEXT("Update Revision"), bufs[i], size);
|
||||
if (res[i] == ERROR_SUCCESS)
|
||||
if (size != bufs[i].Size())
|
||||
res[i] = ERROR_SUCCESS + 1;
|
||||
}
|
||||
}
|
||||
if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS)
|
||||
{
|
||||
s.Add_OptSpaced("(");
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (i == 1)
|
||||
s += "->";
|
||||
if (res[i] != ERROR_SUCCESS)
|
||||
continue;
|
||||
const CByteBuffer &buf = bufs[i];
|
||||
if (buf.Size() == 8)
|
||||
{
|
||||
UInt32 high = GetUi32(buf);
|
||||
if (high != 0)
|
||||
{
|
||||
PrintHex(s, high);
|
||||
s += ".";
|
||||
}
|
||||
PrintHex(s, GetUi32(buf + 4));
|
||||
}
|
||||
}
|
||||
s += ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
Add_LargePages_String(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AddCpuFeatures(AString &s);
|
||||
void AddCpuFeatures(AString &s)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// const unsigned kNumFeatures_Extra = 32; // we check also for unknown features
|
||||
// const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra;
|
||||
const unsigned kNumFeatures = 64;
|
||||
UInt64 flags = 0;
|
||||
for (unsigned i = 0; i < kNumFeatures; i++)
|
||||
{
|
||||
if (IsProcessorFeaturePresent(i))
|
||||
{
|
||||
flags += (UInt64)1 << i;
|
||||
// s.Add_Space_if_NotEmpty();
|
||||
// s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i);
|
||||
}
|
||||
}
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += "f:";
|
||||
PrintHex(s, flags);
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#ifdef __APPLE__
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (My_sysctlbyname_Get_UInt32("hw.pagesize", &v) == 0)
|
||||
{
|
||||
s += "PageSize:";
|
||||
s.Add_UInt32(v >> 10);
|
||||
s += "KB";
|
||||
}
|
||||
}
|
||||
|
||||
#elif !defined(_AIX)
|
||||
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += "hwcap:";
|
||||
{
|
||||
unsigned long h = getauxval(AT_HWCAP);
|
||||
PrintHex(s, h);
|
||||
#ifdef MY_CPU_ARM64
|
||||
if (h & HWCAP_CRC32) s += ":CRC32";
|
||||
if (h & HWCAP_SHA1) s += ":SHA1";
|
||||
if (h & HWCAP_SHA2) s += ":SHA2";
|
||||
if (h & HWCAP_AES) s += ":AES";
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
unsigned long h = getauxval(AT_HWCAP2);
|
||||
#ifndef MY_CPU_ARM
|
||||
if (h != 0)
|
||||
#endif
|
||||
{
|
||||
s += " hwcap2:";
|
||||
PrintHex(s, h);
|
||||
#ifdef MY_CPU_ARM
|
||||
if (h & HWCAP2_CRC32) s += ":CRC32";
|
||||
if (h & HWCAP2_SHA1) s += ":SHA1";
|
||||
if (h & HWCAP2_SHA2) s += ":SHA2";
|
||||
if (h & HWCAP2_AES) s += ":AES";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef UNDER_CE
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
|
||||
EXTERN_C_END
|
||||
|
||||
static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi)
|
||||
{
|
||||
HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
|
||||
if (!ntdll)
|
||||
return FALSE;
|
||||
Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion");
|
||||
if (!func)
|
||||
return FALSE;
|
||||
func(vi);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void GetSystemInfoText(AString &sRes)
|
||||
{
|
||||
{
|
||||
{
|
||||
AString s;
|
||||
#ifdef _WIN32
|
||||
#ifndef UNDER_CE
|
||||
// OSVERSIONINFO vi;
|
||||
OSVERSIONINFOEXW vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
// if (::GetVersionEx(&vi))
|
||||
if (My_RtlGetVersion(&vi))
|
||||
{
|
||||
s += "Windows";
|
||||
if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
|
||||
s.Add_UInt32(vi.dwPlatformId);
|
||||
s += " "; s.Add_UInt32(vi.dwMajorVersion);
|
||||
s += "."; s.Add_UInt32(vi.dwMinorVersion);
|
||||
s += " "; s.Add_UInt32(vi.dwBuildNumber);
|
||||
|
||||
if (vi.wServicePackMajor != 0 || vi.wServicePackMinor != 0)
|
||||
{
|
||||
s += " SP:"; s.Add_UInt32(vi.wServicePackMajor);
|
||||
s += "."; s.Add_UInt32(vi.wServicePackMinor);
|
||||
}
|
||||
s += " Suite:"; PrintHex(s, vi.wSuiteMask);
|
||||
s += " Type:"; s.Add_UInt32(vi.wProductType);
|
||||
// s += " "; s += GetOemString(vi.szCSDVersion);
|
||||
}
|
||||
{
|
||||
s += " OEMCP:";
|
||||
s.Add_UInt32(GetOEMCP());
|
||||
s += " ACP:";
|
||||
s.Add_UInt32(GetACP());
|
||||
}
|
||||
#endif
|
||||
#else // _WIN32
|
||||
|
||||
if (!s.IsEmpty())
|
||||
s.Add_LF();
|
||||
struct utsname un;
|
||||
if (uname(&un) == 0)
|
||||
{
|
||||
s += un.sysname;
|
||||
// s += " : "; s += un.nodename; // we don't want to show name of computer
|
||||
s += " : "; s += un.release;
|
||||
s += " : "; s += un.version;
|
||||
s += " : "; s += un.machine;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Add_sysctlbyname_to_String("kern.version", s);
|
||||
// it's same as "utsname.version"
|
||||
#endif
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
sRes += s;
|
||||
sRes.Add_LF();
|
||||
}
|
||||
|
||||
{
|
||||
AString s, s1, s2;
|
||||
GetSysInfo(s1, s2);
|
||||
if (!s1.IsEmpty() || !s2.IsEmpty())
|
||||
{
|
||||
s = s1;
|
||||
if (s1 != s2 && !s2.IsEmpty())
|
||||
{
|
||||
s += " - ";
|
||||
s += s2;
|
||||
}
|
||||
}
|
||||
{
|
||||
AddCpuFeatures(s);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
sRes += s;
|
||||
sRes.Add_LF();
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
AString s;
|
||||
GetCpuName(s);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
sRes += s;
|
||||
sRes.Add_LF();
|
||||
}
|
||||
}
|
||||
/*
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
{
|
||||
AString s;
|
||||
x86cpuid_all_to_String(s);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
printCallback->Print(s);
|
||||
printCallback->NewLine();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
}
|
||||
12
CPP/Windows/SystemInfo.h
Normal file
12
CPP/Windows/SystemInfo.h
Normal file
@@ -0,0 +1,12 @@
|
||||
// Windows/SystemInfo.h
|
||||
|
||||
#ifndef __WINDOWS_SYSTEM_INFO_H
|
||||
#define __WINDOWS_SYSTEM_INFO_H
|
||||
|
||||
#include "../Common/MyString.h"
|
||||
|
||||
void GetSystemInfoText(AString &s);
|
||||
void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v);
|
||||
void Add_LargePages_String(AString &s);
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace NWindows {
|
||||
|
||||
class CThread
|
||||
class CThread MY_UNCOPYABLE
|
||||
{
|
||||
::CThread thread;
|
||||
public:
|
||||
@@ -17,9 +17,15 @@ public:
|
||||
~CThread() { Close(); }
|
||||
bool IsCreated() { return Thread_WasCreated(&thread) != 0; }
|
||||
WRes Close() { return Thread_Close(&thread); }
|
||||
WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)
|
||||
{ return Thread_Create(&thread, startAddress, parameter); }
|
||||
WRes Wait() { return Thread_Wait(&thread); }
|
||||
// WRes Wait() { return Thread_Wait(&thread); }
|
||||
WRes Wait_Close() { return Thread_Wait_Close(&thread); }
|
||||
|
||||
WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param)
|
||||
{ return Thread_Create(&thread, startAddress, param); }
|
||||
WRes Create_With_Affinity(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, CAffinityMask affinity)
|
||||
{ return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); }
|
||||
WRes Create_With_CpuSet(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, const CCpuSet *cpuSet)
|
||||
{ return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); }
|
||||
|
||||
#ifdef _WIN32
|
||||
operator HANDLE() { return thread; }
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "Defs.h"
|
||||
#include "TimeUtils.h"
|
||||
|
||||
@@ -10,7 +14,9 @@ namespace NTime {
|
||||
|
||||
static const UInt32 kNumTimeQuantumsInSecond = 10000000;
|
||||
static const UInt32 kFileTimeStartYear = 1601;
|
||||
#if !defined(_WIN32) || defined(UNDER_CE)
|
||||
static const UInt32 kDosTimeStartYear = 1980;
|
||||
#endif
|
||||
static const UInt32 kUnixTimeStartYear = 1970;
|
||||
static const UInt64 kUnixTimeOffset =
|
||||
(UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
|
||||
@@ -37,10 +43,6 @@ bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw()
|
||||
static const UInt32 kHighDosTime = 0xFF9FBF7D;
|
||||
static const UInt32 kLowDosTime = 0x210000;
|
||||
|
||||
#define PERIOD_4 (4 * 365 + 1)
|
||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||
|
||||
bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()
|
||||
{
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
@@ -55,6 +57,10 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()
|
||||
|
||||
#else
|
||||
|
||||
#define PERIOD_4 (4 * 365 + 1)
|
||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||
|
||||
unsigned year, mon, day, hour, min, sec;
|
||||
UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);
|
||||
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
@@ -129,7 +135,7 @@ void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw()
|
||||
|
||||
UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw()
|
||||
{
|
||||
return (UInt64)(kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
|
||||
return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
|
||||
}
|
||||
|
||||
bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw()
|
||||
@@ -200,6 +206,7 @@ void GetCurUtcFileTime(FILETIME &ft) throw()
|
||||
{
|
||||
// Both variants provide same low resolution on WinXP: about 15 ms.
|
||||
// But GetSystemTimeAsFileTime is much faster.
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef UNDER_CE
|
||||
SYSTEMTIME st;
|
||||
@@ -208,6 +215,20 @@ void GetCurUtcFileTime(FILETIME &ft) throw()
|
||||
#else
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
UInt64 v = 0;
|
||||
struct timeval now;
|
||||
if (gettimeofday(&now, 0 ) == 0)
|
||||
{
|
||||
v = ((UInt64)now.tv_sec + kUnixTimeOffset) *
|
||||
kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10;
|
||||
}
|
||||
ft.dwLowDateTime = (DWORD)v;
|
||||
ft.dwHighDateTime = (DWORD)(v >> 32);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -114,12 +114,12 @@ bool MySetWindowText(HWND wnd, LPCWSTR s)
|
||||
bool CWindow::GetText(CSysString &s)
|
||||
{
|
||||
s.Empty();
|
||||
int len = GetTextLength();
|
||||
unsigned len = (unsigned)GetTextLength();
|
||||
if (len == 0)
|
||||
return (::GetLastError() == ERROR_SUCCESS);
|
||||
TCHAR *p = s.GetBuf(len);
|
||||
{
|
||||
int len2 = GetText(p, len + 1);
|
||||
unsigned len2 = (unsigned)GetText(p, (int)(len + 1));
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
}
|
||||
@@ -135,12 +135,12 @@ bool CWindow::GetText(UString &s)
|
||||
if (g_IsNT)
|
||||
{
|
||||
s.Empty();
|
||||
int len = GetWindowTextLengthW(_window);
|
||||
unsigned len = (unsigned)GetWindowTextLengthW(_window);
|
||||
if (len == 0)
|
||||
return (::GetLastError() == ERROR_SUCCESS);
|
||||
wchar_t *p = s.GetBuf(len);
|
||||
{
|
||||
int len2 = GetWindowTextW(_window, p, len + 1);
|
||||
unsigned len2 = (unsigned)GetWindowTextW(_window, p, (int)(len + 1));
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ public:
|
||||
bool Update() { return BOOLToBool(::UpdateWindow(_window)); }
|
||||
bool InvalidateRect(LPCRECT rect, bool backgroundErase = true)
|
||||
{ return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); }
|
||||
void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, BoolToBOOL(redraw), 0); }
|
||||
void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, (WPARAM)BoolToBOOL(redraw), 0); }
|
||||
|
||||
LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); }
|
||||
LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); }
|
||||
@@ -244,7 +244,7 @@ public:
|
||||
|
||||
int GetTextLength() const
|
||||
{ return GetWindowTextLength(_window); }
|
||||
UINT GetText(LPTSTR string, int maxCount) const
|
||||
int GetText(LPTSTR string, int maxCount) const
|
||||
{ return GetWindowText(_window, string, maxCount); }
|
||||
bool GetText(CSysString &s);
|
||||
#ifndef _UNICODE
|
||||
|
||||
Reference in New Issue
Block a user