mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-14 21:09:05 +08:00
+add: Long Path support: first steps
This commit is contained in:
parent
538e7ad827
commit
f42616402d
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
// ============================================================================
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include <richedit.h>
|
||||
#pragma warning( pop )
|
||||
|
||||
#include "PathLib.h"
|
||||
#include "Edit.h"
|
||||
#include "Dlapi.h"
|
||||
#include "Version.h"
|
||||
|
||||
166
src/DynStrg.c
166
src/DynStrg.c
@ -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);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <commctrl.h>
|
||||
#include <muiload.h>
|
||||
|
||||
#include "PathLib.h"
|
||||
#include "Dialogs.h"
|
||||
#include "Encoding.h"
|
||||
#include "Config/Config.h"
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include <process.h>
|
||||
//#include <pathcch.h>
|
||||
|
||||
#include "PathLib.h"
|
||||
#include "Edit.h"
|
||||
#include "Styles.h"
|
||||
#include "Dialogs.h"
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -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
319
src/PathLib.c
Normal 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
89
src/PathLib.h
Normal 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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
#include "uthash/utarray.h"
|
||||
|
||||
#include "PathLib.h"
|
||||
#include "Edit.h"
|
||||
#include "Dialogs.h"
|
||||
#include "Encoding.h"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user