diff --git a/res/Notepad3.exe.manifest b/res/Notepad3.exe.manifest index c94716b38..0fb453c68 100644 --- a/res/Notepad3.exe.manifest +++ b/res/Notepad3.exe.manifest @@ -41,7 +41,7 @@ PerMonitorV2,PerMonitor - false + true false diff --git a/src/.clang-format b/src/.clang-format index 2d22a9b81..8cc8ef6d0 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -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 diff --git a/src/Config/Config.cpp b/src/Config/Config.cpp index 10329e0e7..e452ec70a 100644 --- a/src/Config/Config.cpp +++ b/src/Config/Config.cpp @@ -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 #include @@ -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; } // ============================================================================ diff --git a/src/Dialogs.c b/src/Dialogs.c index 7e9f78d40..6a5c66b2e 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -30,6 +30,7 @@ #include #pragma warning( pop ) +#include "PathLib.h" #include "Edit.h" #include "Dlapi.h" #include "Version.h" diff --git a/src/DynStrg.c b/src/DynStrg.c index f5944a512..391c3bc5e 100644 --- a/src/DynStrg.c +++ b/src/DynStrg.c @@ -7,7 +7,6 @@ #include #include #include -//#include #include #include #include @@ -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); +} + +// -------------------------------------------------------------------------- diff --git a/src/DynStrg.h b/src/DynStrg.h index ecaf6eab3..2e5b422a4 100644 --- a/src/DynStrg.h +++ b/src/DynStrg.h @@ -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 diff --git a/src/Helpers.c b/src/Helpers.c index 2a64b77b1..45c341ed8 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -23,8 +23,7 @@ #include #include -//#include - +#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); diff --git a/src/Helpers.h b/src/Helpers.h index 26e8cf7d9..49361f8de 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -807,42 +807,7 @@ void CloseApplication(); // ---------------------------------------------------------------------------- -inline bool PathIsExistingFile(LPCWSTR pszPath) -{ - return (PathFileExists(pszPath) && !PathIsDirectory(pszPath)); -} - -// including 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); } diff --git a/src/MuiLanguage.c b/src/MuiLanguage.c index 8bdf10815..6d14ed2df 100644 --- a/src/MuiLanguage.c +++ b/src/MuiLanguage.c @@ -20,6 +20,7 @@ #include #include +#include "PathLib.h" #include "Dialogs.h" #include "Encoding.h" #include "Config/Config.h" diff --git a/src/Notepad3.c b/src/Notepad3.c index 3d12bb605..453dae7a8 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -28,6 +28,7 @@ #include //#include +#include "PathLib.h" #include "Edit.h" #include "Styles.h" #include "Dialogs.h" diff --git a/src/Notepad3.vcxproj b/src/Notepad3.vcxproj index ff57934c3..9a2644c1f 100644 --- a/src/Notepad3.vcxproj +++ b/src/Notepad3.vcxproj @@ -623,6 +623,7 @@ + @@ -780,6 +781,7 @@ + diff --git a/src/Notepad3.vcxproj.filters b/src/Notepad3.vcxproj.filters index e779b1604..57d92bd8b 100644 --- a/src/Notepad3.vcxproj.filters +++ b/src/Notepad3.vcxproj.filters @@ -423,6 +423,9 @@ Source Files + + Source Files + @@ -605,6 +608,9 @@ Header Files + + Header Files + diff --git a/src/PathLib.c b/src/PathLib.c new file mode 100644 index 000000000..13c82028e --- /dev/null +++ b/src/PathLib.c @@ -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" +// where "" 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 + +// get rid of this: +#include + +#include +#include +#include +#include + +#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)); +} +// ---------------------------------------------------------------------------- + diff --git a/src/PathLib.h b/src/PathLib.h new file mode 100644 index 000000000..0e58b34e3 --- /dev/null +++ b/src/PathLib.h @@ -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 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 + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- diff --git a/src/Styles.c b/src/Styles.c index 6d89ce6fa..f8e112b6d 100644 --- a/src/Styles.c +++ b/src/Styles.c @@ -29,6 +29,7 @@ #include "uthash/utarray.h" +#include "PathLib.h" #include "Edit.h" #include "Dialogs.h" #include "Encoding.h"