summaryrefslogblamecommitdiffstats
path: root/Src/nu/AutoWideFn.h
blob: 5d44dee33732daf4fcfba5e6208700c117bcbff8 (plain) (tree)






























































































































































































                                                                                                            
#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