192 lines
4.0 KiB
C++
192 lines
4.0 KiB
C++
#ifndef NULLSOFT_UTILITY_AUTOWIDEFN_H
|
|
#define NULLSOFT_UTILITY_AUTOWIDEFN_H
|
|
|
|
|
|
/* Winamp defines this, but this little block lets us use this thing outside of Winamp */
|
|
#ifndef FILENAME_SIZE
|
|
#define FILENAME_SIZE (MAX_PATH*4)
|
|
#define REMOVE_FILENAME_SIZE
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include "AutoWide.h"
|
|
#include "AutoChar.h"
|
|
#include <shlwapi.h>
|
|
/*
|
|
Tries to find a filename that underwent a destructive Unicode-to-ANSI conversion
|
|
*/
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4995)
|
|
class AutoWideFn
|
|
{
|
|
public:
|
|
AutoWideFn(const char *narrowFn)
|
|
{
|
|
wideFn[0]=0;
|
|
if (!narrowFn)
|
|
return;
|
|
CreateFile_HACK(narrowFn, wideFn);
|
|
}
|
|
|
|
operator wchar_t *() { return wideFn; }
|
|
bool unicode_find(/*char *path,*/ char *pattern, wchar_t *out, UINT out_ptr, bool dir, HANDLE *f)
|
|
{
|
|
WIN32_FIND_DATAW fd = {0};
|
|
|
|
if (*f == INVALID_HANDLE_VALUE)
|
|
{
|
|
lstrcpyW(out + out_ptr, L"*");
|
|
*f = FindFirstFileW(out, &fd);
|
|
out[out_ptr] = 0;
|
|
if (*f == INVALID_HANDLE_VALUE) return 0;
|
|
}
|
|
else
|
|
{
|
|
if (!FindNextFileW(*f, &fd))
|
|
{
|
|
FindClose(*f);
|
|
*f = INVALID_HANDLE_VALUE;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (*f == INVALID_HANDLE_VALUE) return 0;
|
|
char temp[MAX_PATH*2 + 1] = {0};
|
|
do
|
|
{
|
|
if (dir)
|
|
{
|
|
if (!(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) continue;
|
|
}
|
|
else
|
|
{
|
|
if (fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
|
|
}
|
|
WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, temp, sizeof(temp), 0, 0);
|
|
//wcstombs(temp,fd.cFileName,sizeof(temp));
|
|
if (!_stricmp(temp, pattern))
|
|
{ //found
|
|
lstrcpyW(out + out_ptr, fd.cFileName);
|
|
return 1;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, fd.cAlternateFileName, -1, temp, sizeof(temp), 0, 0);
|
|
if (!_stricmp(temp, pattern))
|
|
{ //found
|
|
lstrcpyW(out + out_ptr, fd.cFileName);
|
|
return 1;
|
|
}
|
|
}
|
|
while (FindNextFileW(*f, &fd));
|
|
FindClose(*f);
|
|
*f = INVALID_HANDLE_VALUE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool unicode_open_recur(char *path, char *ptr, wchar_t *out, UINT out_ptr)
|
|
{
|
|
char * next = strchr(ptr, '\\');
|
|
if (next)
|
|
{ //dig another dir
|
|
HANDLE f = INVALID_HANDLE_VALUE;
|
|
bool found;
|
|
do
|
|
{
|
|
next[0] = 0;
|
|
char * zz = _strdup(ptr);
|
|
char bk = *ptr;
|
|
*ptr = 0;
|
|
found = unicode_find(/*path,*/ zz, out, out_ptr, 1, &f);
|
|
free(zz);
|
|
*ptr = bk;
|
|
next[0] = '\\';
|
|
if (found)
|
|
{
|
|
UINT op_bk = out_ptr;
|
|
while (out_ptr < FILENAME_SIZE && out[out_ptr]) out_ptr++;
|
|
out[out_ptr++] = '\\';
|
|
if (unicode_open_recur(path, next + 1, out, out_ptr))
|
|
{
|
|
if (f != INVALID_HANDLE_VALUE) FindClose(f);
|
|
return 1;
|
|
}
|
|
out_ptr = op_bk;
|
|
out[out_ptr] = 0;
|
|
}
|
|
} while (found);
|
|
}
|
|
else
|
|
{ //final dir
|
|
HANDLE f = INVALID_HANDLE_VALUE;
|
|
char * zz = _strdup(ptr);
|
|
char bk = *ptr;
|
|
*ptr = 0;
|
|
bool found = unicode_find(/*path,*/ zz, out, out_ptr, 0, &f);
|
|
if (!found)
|
|
{
|
|
if (f != INVALID_HANDLE_VALUE)
|
|
{
|
|
FindClose(f);
|
|
f = INVALID_HANDLE_VALUE;
|
|
}
|
|
found = unicode_find(/*path,*/ zz, out, out_ptr, 1, &f);
|
|
}
|
|
free(zz);
|
|
*ptr = bk;
|
|
if (f != INVALID_HANDLE_VALUE) FindClose(f);
|
|
return found;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void CreateFile_HACK(const char * path, wchar_t out[FILENAME_SIZE])
|
|
{
|
|
MultiByteToWideChar(CP_ACP, 0, path, -1, out, FILENAME_SIZE);
|
|
|
|
if (PathIsURLW(out))
|
|
return ;
|
|
|
|
if (!StrChrW(out, L'?'))
|
|
return ; // no unconvertables? Great!
|
|
|
|
// if (PathFileExistsW(out))
|
|
// return ; // no unconvertables? Great!
|
|
|
|
bool found = false;
|
|
|
|
memset(out, 0, FILENAME_SIZE * sizeof(wchar_t));
|
|
|
|
char * _p = _strdup(path);
|
|
char * t = strchr(_p, '\\');
|
|
|
|
if (t)
|
|
{
|
|
char bk = t[1];
|
|
t[1] = 0;
|
|
UINT o = MultiByteToWideChar(CP_ACP, 0, _p, -1, out, FILENAME_SIZE);
|
|
o--;
|
|
t[1] = bk;
|
|
found = unicode_open_recur(_p, t + 1, out, o);
|
|
}
|
|
else
|
|
found = unicode_open_recur(_p, _p, out, 0);
|
|
free(_p);
|
|
|
|
if (!found)
|
|
MultiByteToWideChar(CP_ACP, 0, path, -1, out, FILENAME_SIZE);
|
|
}
|
|
private:
|
|
wchar_t wideFn[FILENAME_SIZE];
|
|
};
|
|
|
|
#pragma warning(pop)
|
|
|
|
#ifdef REMOVE_FILENAME_SIZE
|
|
#undef FILENAME_SIZE
|
|
#endif
|
|
|
|
#endif
|