+add: Long Path support: first steps

This commit is contained in:
METANEOCORTEX\Kotti 2021-08-29 15:00:34 +02:00
parent 538e7ad827
commit f42616402d
15 changed files with 568 additions and 122 deletions

View File

@ -41,7 +41,7 @@
<dpiAwareness>PerMonitorV2,PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
<asmv3:windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<ws2:longPathAware>false</ws2:longPathAware>
<ws2:longPathAware>true</ws2:longPathAware>
</asmv3:windowsSettings>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
<gdiScaling>false</gdiScaling>

View File

@ -8,9 +8,26 @@ TabWidth: 4
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
AlignConsecutiveDeclarations: true
PointerAlignment: Left
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true
ColumnLimit: 0
#BraceWrapping:
# AfterClass: true
# AfterControlStatement: true
# AfterEnum: false
# AfterFunction: true
# AfterNamespace: false
# AfterObjCDeclaration: true
# AfterStruct: true
# AfterUnion: true
# BeforeCatch: true
# BeforeElse: false
# IndentBraces: false
#BreakBeforeBraces: Custom
BreakBeforeBraces: Stroustrup
#BreakBeforeBraces: Allman
Cpp11BracedListStyle: false
FixNamespaceComments: false
SortIncludes: false

View File

@ -21,9 +21,10 @@
#if !defined(NTDDI_VERSION)
#define NTDDI_VERSION 0x06010000 /*NTDDI_WIN7*/
#endif
#define VC_EXTRALEAN 1
#define WIN32_LEAN_AND_MEAN 1
#define NOMINMAX 1
//#define NOMINMAX 1
#include <windows.h>
#include <strsafe.h>
@ -44,6 +45,7 @@ extern "C" {
#include "Notepad3.h"
#include "MuiLanguage.h"
#include "DynStrg.h"
#include "PathLib.h"
}
#include "DarkMode/DarkMode.h"
@ -838,15 +840,17 @@ extern "C" void ClearDestinationsOnRecentDocs()
//
static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
{
WCHAR wchFileExpanded[MAX_PATH] = { L'\0' };
ExpandEnvironmentStrings(lpszFile, wchFileExpanded, COUNTOF(wchFileExpanded));
HPATHL hPathExpanded = Path_Allocate(lpszFile);
Path_ExpandEnvStrings(hPathExpanded);
const bool bIsMaxPath = (Path_GetLength(hPathExpanded) <= MAX_PATH);
bool result = false;
if (PathIsRelative(wchFileExpanded)) {
if (bIsMaxPath && PathIsRelative(Path_Get(hPathExpanded))) {
WCHAR tchBuild[MAX_PATH] = { L'\0' };
// program directory
// program directory
StringCchCopy(tchBuild, COUNTOF(tchBuild), lpszModule);
StringCchCopy(PathFindFileName(tchBuild), COUNTOF(tchBuild), wchFileExpanded);
StringCchCopy(PathFindFileName(tchBuild), COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
@ -856,14 +860,14 @@ static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
StringCchCopy(tchBuild, COUNTOF(tchBuild), lpszModule);
PathCchRemoveFileSpec(tchBuild, COUNTOF(tchBuild));
StringCchCat(tchBuild, COUNTOF(tchBuild), L"\\np3\\");
StringCchCat(tchBuild, COUNTOF(tchBuild), wchFileExpanded);
StringCchCat(tchBuild, COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
}
// Application Data (%APPDATA%)
if (!result && GetKnownFolderPath(FOLDERID_RoamingAppData, tchBuild, COUNTOF(tchBuild))) {
PathCchAppend(tchBuild, COUNTOF(tchBuild), wchFileExpanded);
PathCchAppend(tchBuild, COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
@ -871,7 +875,7 @@ static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
}
// Home (%HOMEPATH%) user's profile dir
if (!result && GetKnownFolderPath(FOLDERID_Profile, tchBuild, COUNTOF(tchBuild))) {
PathCchAppend(tchBuild, COUNTOF(tchBuild), wchFileExpanded);
PathCchAppend(tchBuild, COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
@ -883,10 +887,12 @@ static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
//~ return true;
//~}
}
} else if (PathIsExistingFile(wchFileExpanded)) {
StringCchCopy(lpszFile, MAX_PATH, wchFileExpanded);
}
else if (Path_IsExistingFile(hPathExpanded)) {
StringCchCopy(lpszFile, MAX_PATH, Path_Get(hPathExpanded));
result = true;
}
Path_Release(hPathExpanded);
return result;
}
// ============================================================================

View File

@ -30,6 +30,7 @@
#include <richedit.h>
#pragma warning( pop )
#include "PathLib.h"
#include "Edit.h"
#include "Dlapi.h"
#include "Version.h"

View File

@ -7,7 +7,6 @@
#include <stdlib.h>
#include <tchar.h>
#include <assert.h>
//#include <ctype.h>
#include <stdarg.h>
#include <heapapi.h>
#include <strsafe.h>
@ -32,7 +31,6 @@ typedef struct tagSTRINGW
/* */
/**************************************************/
// direct heap allocation
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(NDEBUG)
#define DEFAULT_ALLOC_FLAGS (HEAP_GENERATE_EXCEPTIONS)
@ -65,39 +63,41 @@ __forceinline size_t SizeOfMemStrg(LPCVOID lpMemory) {
/* */
/**************************************************/
__forceinline STRINGW* STRAPI ToWString(HSTRINGW hstr)
__forceinline STRINGW* ToWStrg(HSTRINGW hstr)
{
if (!hstr)
return NULL;
return (STRINGW*)hstr;
}
__forceinline size_t STRAPI StrlenW(const wchar_t *p) {
__forceinline size_t StrlenW(const wchar_t *p) {
return (!p) ? 0 : wcslen(p);
}
inline static void * STRAPI AllocBuffer(size_t len, size_t char_size, BOOL bZeroMem) {
#define limit_len(len) (((len) < STRINGW_MAX_CCH) ? (len) : (STRINGW_MAX_CCH - 1))
inline static void * AllocBuffer(size_t len, size_t char_size, BOOL bZeroMem) {
if (!s_hndlProcessHeap) {
s_hndlProcessHeap = GetProcessHeap();
}
return AllocMemStrg(len * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
return AllocMemStrg(limit_len(len) * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
}
inline static void * STRAPI ReAllocBuffer(void* pdata, size_t len, size_t char_size, BOOL bZeroMem) {
inline static void * ReAllocBuffer(void* pdata, size_t len, size_t char_size, BOOL bZeroMem) {
if (!s_hndlProcessHeap) {
s_hndlProcessHeap = GetProcessHeap();
}
return ReAllocMemStrg(pdata, len * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
return ReAllocMemStrg(pdata, limit_len(len) * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
}
inline static void STRAPI FreeBuffer(wchar_t * pstr) {
inline static void FreeBuffer(wchar_t * pstr) {
if (!s_hndlProcessHeap) {
s_hndlProcessHeap = GetProcessHeap();
}
FreeMemStrg(pstr);
}
inline static void STRAPI FreeBufferW(STRINGW* pstr) {
inline static void FreeBufferW(STRINGW* pstr) {
if (!pstr->data) {
return;
}
@ -107,17 +107,18 @@ inline static void STRAPI FreeBufferW(STRINGW* pstr) {
pstr->data_length = 0;
}
static void STRAPI AllocW(STRINGW* pstr, size_t len)
static void AllocW(STRINGW* pstr, size_t len)
{
if (len == 0)
FreeBufferW(pstr);
else
{
len = limit_len(len);
size_t const alloc_len = len + 1;
if (!pstr->data) {
pstr->data = AllocBuffer(alloc_len, sizeof(wchar_t), FALSE);
pstr->data = AllocBuffer(alloc_len, sizeof(wchar_t), TRUE);
} else if (len >= pstr->alloc_length) {
pstr->data = ReAllocBuffer(pstr->data, alloc_len, sizeof(wchar_t), FALSE);
pstr->data = ReAllocBuffer(pstr->data, alloc_len, sizeof(wchar_t), TRUE);
}
if (pstr->data) // init
{
@ -129,7 +130,7 @@ static void STRAPI AllocW(STRINGW* pstr, size_t len)
}
}
static void STRAPI AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, size_t copy_index, size_t extra_len)
static void AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, size_t copy_index, size_t extra_len)
{
size_t new_len = copy_len + extra_len;
if (new_len > 0)
@ -141,7 +142,7 @@ static void STRAPI AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, si
}
}
static void STRAPI CopyW(STRINGW *pstr, size_t len, const wchar_t *p) {
static void CopyW(STRINGW *pstr, size_t len, const wchar_t *p) {
if (pstr->data) {
wchar_t *endptr = NULL;
StringCchCopyNExW(pstr->data, pstr->alloc_length, p, len, &endptr, NULL, STR_CCH_FLAGS);
@ -149,16 +150,16 @@ static void STRAPI CopyW(STRINGW *pstr, size_t len, const wchar_t *p) {
}
}
static void STRAPI SetCopyW(STRINGW* pstr, size_t len, const wchar_t* p)
static void SetCopyW(STRINGW* pstr, size_t len, const wchar_t* p)
{
AllocW(pstr, len);
CopyW(pstr, len, p);
}
static wchar_t* STRAPI CopyOldDataW(STRINGW* pstr, size_t* outLen)
static wchar_t* CopyOldDataW(STRINGW* pstr, size_t* outLen)
{
size_t old_len = StrlenW(pstr->data);
wchar_t* ptr = AllocBuffer(old_len + 1, sizeof(wchar_t), FALSE);
wchar_t* ptr = AllocBuffer(old_len + 1, sizeof(wchar_t), TRUE);
if (ptr)
{
wchar_t *endptr = NULL;
@ -168,7 +169,7 @@ static wchar_t* STRAPI CopyOldDataW(STRINGW* pstr, size_t* outLen)
return ptr;
}
static void STRAPI FreeUnusedData(STRINGW *pstr)
static void FreeUnusedData(STRINGW *pstr)
{
if ((pstr->data_length + 1) != pstr->alloc_length) {
size_t old_len = 0;
@ -183,7 +184,7 @@ static void STRAPI FreeUnusedData(STRINGW *pstr)
}
}
static void STRAPI CopyConcatW(STRINGW *pstr, size_t len1, const wchar_t *p1, size_t len2, const wchar_t *p2)
static void CopyConcatW(STRINGW *pstr, size_t len1, const wchar_t *p1, size_t len2, const wchar_t *p2)
{
size_t const new_len = len1 + len2;
if (new_len != 0)
@ -195,7 +196,7 @@ static void STRAPI CopyConcatW(STRINGW *pstr, size_t len1, const wchar_t *p1, si
}
}
static void STRAPI ConcatW(STRINGW* pstr, size_t len, const wchar_t* p)
static void ConcatW(STRINGW* pstr, size_t len, const wchar_t* p)
{
if (len == 0)
return;
@ -222,13 +223,13 @@ static void STRAPI ConcatW(STRINGW* pstr, size_t len, const wchar_t* p)
}
static void STRAPI FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
static void FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
va_list prev_list = args;
va_list orig_list = args;
size_t max_len = 0;
const wchar_t * p;
@ -367,6 +368,7 @@ static void STRAPI FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
default:
assert(0); /* unknown format */
break;
}
}
max_len += item_len;
@ -375,9 +377,9 @@ static void STRAPI FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
AllocW(pstr, max_len);
wchar_t* endptr = NULL;
StringCchVPrintfExW(pstr->data, pstr->alloc_length, &endptr, NULL, STR_CCH_FLAGS, fmt, prev_list);
StringCchVPrintfExW(pstr->data, pstr->alloc_length, &endptr, NULL, STR_CCH_FLAGS, fmt, orig_list);
pstr->data_length = (size_t)(endptr - pstr->data);
va_end(prev_list);
va_end(orig_list);
}
@ -396,18 +398,9 @@ HSTRINGW STRAPI StrgCreate()
}
//~void STRAPI StrgReserveBuffer(HSTRINGW hstr, size_t len) {
//~
//~ STRINGW* ptr = ToWString(hstr);
//~ if (!ptr)
//~ return;
//~ AllocW(ptr, len);
//~}
void STRAPI StrgDestroy(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
FreeBufferW(pstr);
@ -417,7 +410,7 @@ void STRAPI StrgDestroy(HSTRINGW hstr)
int STRAPI StrgSet(HSTRINGW hstr, const wchar_t* str)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return -1;
SetCopyW(pstr, StrlenW(str), str);
@ -427,7 +420,7 @@ int STRAPI StrgSet(HSTRINGW hstr, const wchar_t* str)
const wchar_t* STRAPI StrgGet(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
return pstr->data;
@ -436,7 +429,7 @@ const wchar_t* STRAPI StrgGet(HSTRINGW hstr)
size_t STRAPI StrgGetLength(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
return pstr->data_length;
@ -445,7 +438,7 @@ size_t STRAPI StrgGetLength(HSTRINGW hstr)
size_t STRAPI StrgGetAllocLength(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
return pstr->alloc_length;
@ -460,7 +453,7 @@ int STRAPI StrgIsEmpty(HSTRINGW hstr)
void STRAPI StrgFreeExtra(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
FreeUnusedData(pstr);
@ -469,7 +462,7 @@ void STRAPI StrgFreeExtra(HSTRINGW hstr)
void STRAPI StrgEmpty(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
FreeBufferW(pstr);
@ -478,7 +471,7 @@ void STRAPI StrgEmpty(HSTRINGW hstr)
void STRAPI StrgSetAt(HSTRINGW hstr, size_t index, wchar_t ch)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
if (index >= pstr->data_length)
@ -492,7 +485,7 @@ void STRAPI StrgSetAt(HSTRINGW hstr, size_t index, wchar_t ch)
wchar_t STRAPI StrgGetAt(HSTRINGW hstr, size_t index)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return L'\0';
if (index >= pstr->data_length)
@ -506,7 +499,7 @@ wchar_t STRAPI StrgGetAt(HSTRINGW hstr, size_t index)
void STRAPI StrgCat(HSTRINGW hstr, const wchar_t* str)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
ConcatW(pstr, StrlenW(str), str);
@ -515,7 +508,7 @@ void STRAPI StrgCat(HSTRINGW hstr, const wchar_t* str)
size_t STRAPI StrgInsert(HSTRINGW hstr, size_t index, const wchar_t* str)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@ -548,7 +541,7 @@ size_t STRAPI StrgInsert(HSTRINGW hstr, size_t index, const wchar_t* str)
size_t STRAPI StrgInsertCh(HSTRINGW hstr, size_t index, wchar_t c)
{
STRINGW *pstr = ToWString(hstr);
STRINGW *pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@ -573,7 +566,7 @@ size_t STRAPI StrgInsertCh(HSTRINGW hstr, size_t index, wchar_t c)
size_t STRAPI StrgReplace(HSTRINGW hstr, const wchar_t* pOld, const wchar_t* pNew)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@ -640,7 +633,7 @@ size_t STRAPI StrgRemove(HSTRINGW hstr, const wchar_t *str)
size_t STRAPI StrgReplaceCh(HSTRINGW hstr, wchar_t chOld, wchar_t chNew)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@ -665,7 +658,7 @@ size_t STRAPI StrgReplaceCh(HSTRINGW hstr, wchar_t chOld, wchar_t chNew)
size_t STRAPI StrgRemoveCh(HSTRINGW hstr, wchar_t chRemove)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@ -693,7 +686,7 @@ size_t STRAPI StrgRemoveCh(HSTRINGW hstr, wchar_t chRemove)
size_t STRAPI StrgDelete(HSTRINGW hstr, size_t index, size_t count)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@ -711,7 +704,7 @@ size_t STRAPI StrgDelete(HSTRINGW hstr, size_t index, size_t count)
void STRAPI StrgToUpper(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
_wcsupr_s(pstr->data, pstr->data_length);
@ -720,7 +713,7 @@ void STRAPI StrgToUpper(HSTRINGW hstr)
void STRAPI StrgToLower(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
_wcslwr_s(pstr->data, pstr->data_length);
@ -729,7 +722,7 @@ void STRAPI StrgToLower(HSTRINGW hstr)
void STRAPI StrgReverse(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
_wcsrev(pstr->data);
@ -738,7 +731,7 @@ void STRAPI StrgReverse(HSTRINGW hstr)
void STRAPI StrgTrimRight(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
@ -767,7 +760,7 @@ void STRAPI StrgTrimRight(HSTRINGW hstr)
void STRAPI StrgTrimLeft(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
@ -794,7 +787,7 @@ void STRAPI StrgTrim(HSTRINGW hstr)
size_t STRAPI StrgFind(HSTRINGW hstr, const wchar_t* sub, size_t start)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@ -809,7 +802,7 @@ size_t STRAPI StrgFind(HSTRINGW hstr, const wchar_t* sub, size_t start)
size_t STRAPI StrgFindCh(HSTRINGW hstr, wchar_t ch, size_t start)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@ -824,7 +817,7 @@ size_t STRAPI StrgFindCh(HSTRINGW hstr, wchar_t ch, size_t start)
size_t STRAPI StrgReverseFind(HSTRINGW hstr, wchar_t ch)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@ -836,7 +829,7 @@ size_t STRAPI StrgReverseFind(HSTRINGW hstr, wchar_t ch)
size_t STRAPI StrgFindOneOf(HSTRINGW hstr, const wchar_t* char_set)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@ -847,12 +840,12 @@ size_t STRAPI StrgFindOneOf(HSTRINGW hstr, const wchar_t* char_set)
HSTRINGW STRAPI StrgCopy(HSTRINGW hstr)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
HSTRINGW hCopy = StrgCreate();
STRINGW* pCopy = ToWString(hCopy);
STRINGW* pCopy = ToWStrg(hCopy);
SetCopyW(pCopy, pstr->data_length, pstr->data);
return hCopy;
@ -861,7 +854,7 @@ HSTRINGW STRAPI StrgCopy(HSTRINGW hstr)
HSTRINGW STRAPI StrgMid(HSTRINGW hstr, size_t start, size_t count)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
@ -873,7 +866,7 @@ HSTRINGW STRAPI StrgMid(HSTRINGW hstr, size_t start, size_t count)
assert(start + count <= pstr->data_length);
HSTRINGW hCopy = StrgCreate();
STRINGW* pCopy = ToWString(hCopy);
STRINGW* pCopy = ToWStrg(hCopy);
if (start == 0 && start + count == pstr->data_length) {
SetCopyW(pCopy, pstr->data_length, pstr->data);
@ -887,12 +880,12 @@ HSTRINGW STRAPI StrgMid(HSTRINGW hstr, size_t start, size_t count)
HSTRINGW STRAPI StrgLeft(HSTRINGW hstr, size_t count)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
HSTRINGW hCopy = StrgCreate();
STRINGW* pCopy = ToWString(hCopy);
STRINGW* pCopy = ToWStrg(hCopy);
if (count >= pstr->data_length) {
SetCopyW(pCopy, pstr->data_length, pstr->data);
@ -905,12 +898,12 @@ HSTRINGW STRAPI StrgLeft(HSTRINGW hstr, size_t count)
HSTRINGW STRAPI StrgRight(HSTRINGW hstr, size_t count)
{
STRINGW* pstr = ToWString(hstr);
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
HSTRINGW hCopy = StrgCreate();
STRINGW* pCopy = ToWString(hCopy);
STRINGW* pCopy = ToWStrg(hCopy);
if (count >= pstr->data_length) {
SetCopyW(pCopy, pstr->data_length, pstr->data);
@ -923,7 +916,7 @@ HSTRINGW STRAPI StrgRight(HSTRINGW hstr, size_t count)
void STRAPI StrgFormat(HSTRINGW hstr, const wchar_t* fmt, ...)
{
STRINGW *pstr = ToWString(hstr);
STRINGW* const pstr = ToWStrg(hstr);
if (!pstr)
return;
va_list args;
@ -932,3 +925,38 @@ void STRAPI StrgFormat(HSTRINGW hstr, const wchar_t* fmt, ...)
va_end(args);
}
// --------------------------------------------------------------------------
// Only for PathLib: ensure buffer size is at least MAX_PATH
// NP3_PATH_LIB_IMPLEMENTATION
wchar_t* STRAPI StrgAccessMaxPathBuf(HSTRINGW hstr, size_t min_len)
{
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
if (pstr->alloc_length <= min_len) {
size_t old_len = 0;
wchar_t* pOld = CopyOldDataW(pstr, &old_len);
FreeBufferW(pstr);
SetCopyW(pstr, min_len, pOld);
FreeBuffer(pOld);
}
return pstr->data;
}
void STRAPI StrgSanitize(HSTRINGW hstr)
{
STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
// ensure buffer limit
ptrdiff_t const len = (ptrdiff_t)pstr->alloc_length - 1;
if (len > 0) {
pstr->data[len] = L'\0';
}
pstr->data_length = StrlenW(pstr->data);
}
// --------------------------------------------------------------------------

View File

@ -8,7 +8,11 @@
/* calls instead of using void* pointer */
/**************************************************/
#ifndef DECLARE_HANDLE
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
#define DECLARE_HANDLE(name) \
struct name##__ { \
int unused; \
}; \
typedef struct name##__ *name
#endif
#define STRAPI __stdcall
@ -23,7 +27,6 @@ DECLARE_HANDLE(HSTRINGW);
#define STRINGW_INVALID_SIZE ((size_t)-1)
HSTRINGW STRAPI StrgCreate();
//~void STRAPI StrgReserveBuffer(HSTRINGW hstr, size_t len);
void STRAPI StrgDestroy(HSTRINGW hstr);
size_t STRAPI StrgGetLength(HSTRINGW hstr);
@ -67,3 +70,11 @@ HSTRINGW STRAPI StrgRight(HSTRINGW hstr, size_t count);
void STRAPI StrgFormat(HSTRINGW hstr, const wchar_t* fmt, ...);
// use for PathLib Only !
#ifdef NP3_PATH_LIB_IMPLEMENTATION
wchar_t* STRAPI StrgAccessMaxPathBuf(HSTRINGW hstr, size_t min_len);
void STRAPI StrgSanitize(HSTRINGW hstr); // correct strg length after buffer access
#endif

View File

@ -23,8 +23,7 @@
#include <ctype.h>
#include <wchar.h>
//#include <pathcch.h>
#include "PathLib.h"
#include "Edit.h"
#include "Encoding.h"
#include "MuiLanguage.h"
@ -1625,8 +1624,8 @@ DWORD NormalizePathEx(LPWSTR lpszPath, DWORD cchBuffer, bool bRealPath, bool bSe
StringCchCopy(lpszPath, cchBuffer, p);
}
}
CloseHandle(hFile);
}
CloseHandle(hFile);
}
return (DWORD)StringCchLen(lpszPath, cchBuffer);

View File

@ -807,42 +807,7 @@ void CloseApplication();
// ----------------------------------------------------------------------------
inline bool PathIsExistingFile(LPCWSTR pszPath)
{
return (PathFileExists(pszPath) && !PathIsDirectory(pszPath));
}
// including <pathcch.h> and linking against pathcch.lib
// api-ms-win-core-path-l1-1-0.dll library : Minimum supported client is Windows 8 :-/
// so switch back to previous (deprecated) methods:
inline HRESULT PathCchAppend(PWSTR p,size_t l,PCWSTR a)
{
UNREFERENCED_PARAMETER(l);
return (PathAppend(p,a) ? S_OK : E_FAIL);
}
inline HRESULT PathCchCanonicalize(PWSTR p,size_t l,PCWSTR a)
{
UNREFERENCED_PARAMETER(l);
return (PathCanonicalize(p,a) ? S_OK : E_FAIL);
}
inline HRESULT PathCchRenameExtension(PWSTR p,size_t l,PCWSTR a)
{
UNREFERENCED_PARAMETER(l);
return (PathRenameExtension(p,a) ? S_OK : E_FAIL);
}
inline HRESULT PathCchRemoveFileSpec(PWSTR p,size_t l)
{
UNREFERENCED_PARAMETER(l);
return (PathRemoveFileSpec(p) ? S_OK : E_FAIL);
}
inline bool IsReadOnly(const DWORD dwFileAttr)
{
return ((dwFileAttr != INVALID_FILE_ATTRIBUTES) && (dwFileAttr & FILE_ATTRIBUTE_READONLY));
}
inline int PointSizeToFontHeight(const float fPtHeight, const HDC hdc)
{
inline int PointSizeToFontHeight(const float fPtHeight, const HDC hdc) {
return -MulDiv(float2int(fPtHeight * 100.0f), GetDeviceCaps(hdc, LOGPIXELSY), 72 * SC_FONT_SIZE_MULTIPLIER);
}

View File

@ -20,6 +20,7 @@
#include <commctrl.h>
#include <muiload.h>
#include "PathLib.h"
#include "Dialogs.h"
#include "Encoding.h"
#include "Config/Config.h"

View File

@ -28,6 +28,7 @@
#include <process.h>
//#include <pathcch.h>
#include "PathLib.h"
#include "Edit.h"
#include "Styles.h"
#include "Dialogs.h"

View File

@ -623,6 +623,7 @@
<ClCompile Include="crypto\rijndael-api-fst.c" />
<ClCompile Include="crypto\sha-256.c" />
<ClCompile Include="DynStrg.c" />
<ClCompile Include="PathLib.c" />
<ClCompile Include="StyleLexers\EditLexer.c" />
<ClCompile Include="StyleLexers\styleLexDart.c" />
<ClCompile Include="StyleLexers\styleLexJulia.c" />
@ -780,6 +781,7 @@
<ClInclude Include="crypto\sha-256.h" />
<ClInclude Include="..\language\common_res.h" />
<ClInclude Include="DynStrg.h" />
<ClInclude Include="PathLib.h" />
<ClInclude Include="tinyexpr\tinyexpr.h" />
<ClInclude Include="uchardet\uchardet\src\CharDistribution.h" />
<ClInclude Include="uchardet\uchardet\src\JpCntx.h" />

View File

@ -423,6 +423,9 @@
<ClCompile Include="DynStrg.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PathLib.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dlapi.h">
@ -605,6 +608,9 @@
<ClInclude Include="DynStrg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PathLib.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\res\Copy.cur">

319
src/PathLib.c Normal file
View File

@ -0,0 +1,319 @@
// ============================================================================
//
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
//
// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
//
// In the Windows API (with some exceptions discussed in the following paragraphs),
// the maximum length for a path is MAX_PATH, which is defined as 260 characters.
// A local path is structured in the following order: drive letter, colon, backslash,
// name components separated by backslashes, and a terminating null character.
// For example, the maximum path on drive D is "D:\some 256-character path string<NUL>"
// where "<NUL>" represents the invisible terminating null character for the current
// system codepage.
// (The characters < > are used here for visual clarity and cannot be part of a valid path string.)
//
// The Windows API has many functions that also have Unicode versions to permit an
// extended-length path for a maximum total path length of 32767 characters.
// This type of path is composed of components separated by backslashes,
// each up to the value returned in the lpMaximumComponentLength parameter of the
// GetVolumeInformation function (this value is commonly 255 characters).
// To specify an extended-length path, use the "\\?\" prefix. For example,
// "\\?\D:\very long path".
//
// The "\\?\" prefix can also be used with paths constructed according to the universal
// naming convention (UNC). To specify such a path using UNC, use the "\\?\UNC\" prefix.
// For example, "\\?\UNC\server\share", where "server" is the name of the computer and
// "share" is the name of the shared folder.
// These prefixes are not used as part of the path itself.
// They indicate that the path should be passed to the system with minimal modification,
// which means that you cannot use forward slashes to represent path separators,
// or a period to represent the current directory, or double dots to represent the
// parent directory. Because you cannot use the "\\?\" prefix with a relative path,
// relative paths are always limited to a total of MAX_PATH characters.
//
// There is no need to perform any Unicode normalization on path and file name strings
// for use by the Windows file I/O API functions because the file system treats path and
// file names as an opaque sequence of WCHARs. Any normalization that your application
// requires should be performed with this in mind, external of any calls to related
// Windows file I/O API functions.
//
// When using an API to create a directory, the specified path cannot be so long that you
// cannot append an 8.3 file name (that is, the directory name cannot exceed MAX_PATH minus 12).
//
// The shell and the file system have different requirements.
// It is possible to create a path with the Windows API that the shell user interface
// is not able to interpret properly.
//
// ============================================================================
// ============================================================================
// TODO: if (IsWindows10OrGreater() && OptInRemovedMaxPathLimit()) {}
// https://docs.microsoft.com/de-de/windows/win32/api/fileapi/nf-fileapi-getfileattributesa
//
// These are the directory management functions that no longer have MAX_PATH restrictions
// if you opt - in to long path behavior :
// - CreateDirectoryW
// - CreateDirectoryExW
// - GetCurrentDirectoryW
// - RemoveDirectoryW
// - SetCurrentDirectoryW
//
// These are the file management functions that no longer have MAX_PATH restrictions
// if you opt - in to long path behavior :
// - CopyFileW
// - CopyFile2
// - CopyFileExW
// - CreateFileW
// - CreateFile2
// - CreateHardLinkW
// - CreateSymbolicLinkW
// - DeleteFileW
// - FindFirstFileW
// - FindFirstFileExW
// - FindNextFileW
// - GetFileAttributesW
// - GetFileAttributesExW
// - SetFileAttributesW
// - GetFullPathNameW
// - GetLongPathNameW
// - MoveFileW
// - MoveFileExW
// - MoveFileWithProgressW
// - ReplaceFileW
// - SearchPathW
// - FindFirstFileNameW
// - FindNextFileNameW
// - FindFirstStreamW
// - FindNextStreamW
// - GetCompressedFileSizeW
// - GetFinalPathNameByHandleW
//
// ============================================================================
#if !defined(WINVER)
#define WINVER 0x602 /*_WIN32_WINNT_WIN8*/
#endif
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x602 /*_WIN32_WINNT_WIN8*/
#endif
#if !defined(NTDDI_VERSION)
#define NTDDI_VERSION 0x06020000 /*NTDDI_WIN7*/
#endif
#define VC_EXTRALEAN 1
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
// get rid of this:
#include <shlwapi.h>
#include <fileapi.h>
#include <pathcch.h>
#include <processenv.h>
#include <stdbool.h>
#define NP3_PATH_LIB_IMPLEMENTATION 1
#include "DynStrg.h"
#include "PathLib.h"
/**************************************************/
/* */
/* PRIVATE API */
/* */
/**************************************************/
const wchar_t* const LONG_PATH_PREFIX = L"\\\\?\\";
static bool OptInRemoveMaxPathLimit()
{
static int s_MaxPathLimitRemoved = -1;
switch (s_MaxPathLimitRemoved) {
case -1: {
// Function pointer to driver function
BOOLEAN(WINAPI * pRtlAreLongPathsEnabled)(void) = NULL;
s_MaxPathLimitRemoved = 0; // at least called once
HINSTANCE const hNTdllDll = LoadLibrary(L"ntdll.dll");
if (hNTdllDll) {
// get the function pointer to RtlAreLongPathsEnabled
pRtlAreLongPathsEnabled = (BOOLEAN(WINAPI*)(void))GetProcAddress(hNTdllDll, "RtlAreLongPathsEnabled");
if (pRtlAreLongPathsEnabled != NULL) {
s_MaxPathLimitRemoved = pRtlAreLongPathsEnabled() ? 1 : 0;
}
FreeLibrary(hNTdllDll);
}
return (s_MaxPathLimitRemoved == 1);
}
case 1:
return true;
default:
break;
}
return false;
}
// ----------------------------------------------------------------------------
__forceinline HSTRINGW ToHStrgW(HPATHL hpth)
{
if (!hpth)
return NULL;
return (HSTRINGW)hpth;
}
// ----------------------------------------------------------------------------
/**************************************************/
/* */
/* PUBLIC API */
/* */
/**************************************************/
HPATHL PTHAPI Path_Allocate(const wchar_t* path)
{
HSTRINGW hstr = StrgCreate();
if (path) {
StrgSet(hstr, path);
}
return (HPATHL)hstr;
}
// ----------------------------------------------------------------------------
void PTHAPI Path_Release(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
StrgDestroy(hstr);
}
// ----------------------------------------------------------------------------
int PTHAPI Path_Reset(HPATHL hpth, const wchar_t* path)
{
HSTRINGW hstr = ToHStrgW(hpth);
return StrgSet(hstr, path);
}
// ----------------------------------------------------------------------------
size_t PTHAPI Path_GetLength(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
return StrgGetLength(hstr);
}
// ----------------------------------------------------------------------------
bool PTHAPI Path_RemoveFileSpec(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
if (!hpth)
return false;
LPWSTR wbuf = StrgAccessMaxPathBuf(hstr, MAX_PATH);
size_t cch = StrgGetAllocLength(hstr);
bool const bOK = SUCCEEDED(PathCchRemoveFileSpec(wbuf, cch));
StrgSanitize(hstr);
return bOK;
}
// ----------------------------------------------------------------------------
void PTHAPI Path_ExpandEnvStrings(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
if (!hpth)
return;
LPCWSTR const path_buf = StrgGet(hstr);
HSTRINGW hExPath = StrgCreate();
size_t const min_len = max(ExpandEnvironmentStrings(path_buf, NULL, 0), MAX_PATH);
LPWSTR expth_buf = StrgAccessMaxPathBuf(hExPath, min_len);
DWORD const nSize = (DWORD)StrgGetAllocLength(hExPath);
ExpandEnvironmentStrings(path_buf, expth_buf, nSize);
StrgSanitize(hExPath);
StrgSet(hstr, expth_buf);
StrgDestroy(hExPath);
}
// ----------------------------------------------------------------------------
bool PTHAPI Path_IsExistingFile(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
if (!hpth)
return false;
HSTRINGW hxpth = StrgCopy(hstr);
if (!OptInRemoveMaxPathLimit()) {
StrgInsert(hxpth, 0, L"\\\\?\\");
}
LPCWSTR expth_buf = StrgAccessMaxPathBuf(hxpth, 1);
DWORD const dwFileAttrib = GetFileAttributesW(expth_buf);
bool const bAccessOK = (dwFileAttrib != INVALID_FILE_ATTRIBUTES);
//if (!bAccessOK) {
// DWORD const dwError = GetLastError();
// switch (dwError) {
// case ERROR_FILE_NOT_FOUND:
// break;
// case ERROR_PATH_NOT_FOUND:
// break;
// case ERROR_ACCESS_DENIED:
// break;
// default:
// break;
// }
//}
bool const bIsDirectory = (dwFileAttrib & FILE_ATTRIBUTE_DIRECTORY);
return (bAccessOK && !bIsDirectory);
}
// ----------------------------------------------------------------------------
// ============================================================================
// ============================================================================
const wchar_t* PTHAPI Path_Get(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
return StrgGet(hstr);
}
// ----------------------------------------------------------------------------
size_t PTHAPI Path_GetBufCount(HPATHL hpth)
{
HSTRINGW hstr = ToHStrgW(hpth);
return StrgGetAllocLength(hstr);
}
// ----------------------------------------------------------------------------
// get wchar buffer with at least MAX_PATH size
// TODO: get rid of this intermediate state handler
wchar_t *PTHAPI Path_AccessBuf(HPATHL hpth, size_t len)
{
HSTRINGW hstr = ToHStrgW(hpth);
return StrgAccessMaxPathBuf(hstr, max(len, MAX_PATH));
}
// ----------------------------------------------------------------------------

89
src/PathLib.h Normal file
View File

@ -0,0 +1,89 @@
/****************************************************************/
#pragma once
/**************************************************/
/* Declared in WINNT.H */
/* */
/* Provides bottom line type safety in function */
/* calls instead of using void* pointer */
/**************************************************/
#ifndef DECLARE_HANDLE
#define DECLARE_HANDLE(name) \
struct name##__ { \
int unused; \
}; \
typedef struct name##__ *name
#endif
#define PTHAPI __stdcall
DECLARE_HANDLE(HPATHL);
/**************************************************/
/* */
/* DYNAMIC WIDCHAR LONG PATH */
/* */
/**************************************************/
HPATHL PTHAPI Path_Allocate(const wchar_t* path);
void PTHAPI Path_Release(HPATHL hstr);
int PTHAPI Path_Reset(HPATHL hpth, const wchar_t* path);
size_t PTHAPI Path_GetLength(HPATHL hpth);
bool PTHAPI Path_RemoveFileSpec(HPATHL hpth);
void PTHAPI Path_ExpandEnvStrings(HPATHL hpth);
bool PTHAPI Path_IsExistingFile(HPATHL hpth);
// -------------------------------------------------------
const wchar_t* PTHAPI Path_Get(HPATHL hpth);
size_t PTHAPI Path_GetBufCount(HPATHL hpth);
// get wchar buffer with at least MAX_PATH size
// TODO: get rid of this intermediate state handler
wchar_t* PTHAPI Path_AccessBuf(HPATHL hpth, size_t len);
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
inline bool PathIsExistingFile(LPCWSTR pszPath)
{
return (PathFileExists(pszPath) && !PathIsDirectory(pszPath));
}
inline bool IsReadOnly(const DWORD dwFileAttr)
{
return ((dwFileAttr != INVALID_FILE_ATTRIBUTES) && (dwFileAttr & FILE_ATTRIBUTE_READONLY));
}
#ifndef NP3_PATH_LIB_IMPLEMENTATION
// including <pathcch.h> and linking against pathcch.lib
// api-ms-win-core-path-l1-1-0.dll library : Minimum supported client is Windows 8 :-/
// so switch back to previous (deprecated) methods:
inline HRESULT PathCchAppend(PWSTR p, size_t l, PCWSTR a)
{
UNREFERENCED_PARAMETER(l);
return (PathAppend(p, a) ? S_OK : S_FALSE);
}
inline HRESULT PathCchCanonicalize(PWSTR p, size_t l, PCWSTR a)
{
UNREFERENCED_PARAMETER(l);
return (PathCanonicalize(p, a) ? S_OK : S_FALSE);
}
inline HRESULT PathCchRenameExtension(PWSTR p, size_t l, PCWSTR a)
{
UNREFERENCED_PARAMETER(l);
return (PathRenameExtension(p, a) ? S_OK : S_FALSE);
}
inline HRESULT PathCchRemoveFileSpec(PWSTR p, size_t l)
{
UNREFERENCED_PARAMETER(l);
return (PathRemoveFileSpec(p) ? S_OK : S_FALSE);
}
#endif
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

View File

@ -29,6 +29,7 @@
#include "uthash/utarray.h"
#include "PathLib.h"
#include "Edit.h"
#include "Dialogs.h"
#include "Encoding.h"