AutoWideFn.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #ifndef NULLSOFT_UTILITY_AUTOWIDEFN_H
  2. #define NULLSOFT_UTILITY_AUTOWIDEFN_H
  3. /* Winamp defines this, but this little block lets us use this thing outside of Winamp */
  4. #ifndef FILENAME_SIZE
  5. #define FILENAME_SIZE (MAX_PATH*4)
  6. #define REMOVE_FILENAME_SIZE
  7. #endif
  8. #include <windows.h>
  9. #include "AutoWide.h"
  10. #include "AutoChar.h"
  11. #include <shlwapi.h>
  12. /*
  13. Tries to find a filename that underwent a destructive Unicode-to-ANSI conversion
  14. */
  15. #pragma warning(push)
  16. #pragma warning(disable:4995)
  17. class AutoWideFn
  18. {
  19. public:
  20. AutoWideFn(const char *narrowFn)
  21. {
  22. wideFn[0]=0;
  23. if (!narrowFn)
  24. return;
  25. CreateFile_HACK(narrowFn, wideFn);
  26. }
  27. operator wchar_t *() { return wideFn; }
  28. bool unicode_find(/*char *path,*/ char *pattern, wchar_t *out, UINT out_ptr, bool dir, HANDLE *f)
  29. {
  30. WIN32_FIND_DATAW fd = {0};
  31. if (*f == INVALID_HANDLE_VALUE)
  32. {
  33. lstrcpyW(out + out_ptr, L"*");
  34. *f = FindFirstFileW(out, &fd);
  35. out[out_ptr] = 0;
  36. if (*f == INVALID_HANDLE_VALUE) return 0;
  37. }
  38. else
  39. {
  40. if (!FindNextFileW(*f, &fd))
  41. {
  42. FindClose(*f);
  43. *f = INVALID_HANDLE_VALUE;
  44. return 0;
  45. }
  46. }
  47. if (*f == INVALID_HANDLE_VALUE) return 0;
  48. char temp[MAX_PATH*2 + 1] = {0};
  49. do
  50. {
  51. if (dir)
  52. {
  53. if (!(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) continue;
  54. }
  55. else
  56. {
  57. if (fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
  58. }
  59. WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, temp, sizeof(temp), 0, 0);
  60. //wcstombs(temp,fd.cFileName,sizeof(temp));
  61. if (!_stricmp(temp, pattern))
  62. { //found
  63. lstrcpyW(out + out_ptr, fd.cFileName);
  64. return 1;
  65. }
  66. WideCharToMultiByte(CP_ACP, 0, fd.cAlternateFileName, -1, temp, sizeof(temp), 0, 0);
  67. if (!_stricmp(temp, pattern))
  68. { //found
  69. lstrcpyW(out + out_ptr, fd.cFileName);
  70. return 1;
  71. }
  72. }
  73. while (FindNextFileW(*f, &fd));
  74. FindClose(*f);
  75. *f = INVALID_HANDLE_VALUE;
  76. return 0;
  77. }
  78. bool unicode_open_recur(char *path, char *ptr, wchar_t *out, UINT out_ptr)
  79. {
  80. char * next = strchr(ptr, '\\');
  81. if (next)
  82. { //dig another dir
  83. HANDLE f = INVALID_HANDLE_VALUE;
  84. bool found;
  85. do
  86. {
  87. next[0] = 0;
  88. char * zz = _strdup(ptr);
  89. char bk = *ptr;
  90. *ptr = 0;
  91. found = unicode_find(/*path,*/ zz, out, out_ptr, 1, &f);
  92. free(zz);
  93. *ptr = bk;
  94. next[0] = '\\';
  95. if (found)
  96. {
  97. UINT op_bk = out_ptr;
  98. while (out_ptr < FILENAME_SIZE && out[out_ptr]) out_ptr++;
  99. out[out_ptr++] = '\\';
  100. if (unicode_open_recur(path, next + 1, out, out_ptr))
  101. {
  102. if (f != INVALID_HANDLE_VALUE) FindClose(f);
  103. return 1;
  104. }
  105. out_ptr = op_bk;
  106. out[out_ptr] = 0;
  107. }
  108. } while (found);
  109. }
  110. else
  111. { //final dir
  112. HANDLE f = INVALID_HANDLE_VALUE;
  113. char * zz = _strdup(ptr);
  114. char bk = *ptr;
  115. *ptr = 0;
  116. bool found = unicode_find(/*path,*/ zz, out, out_ptr, 0, &f);
  117. if (!found)
  118. {
  119. if (f != INVALID_HANDLE_VALUE)
  120. {
  121. FindClose(f);
  122. f = INVALID_HANDLE_VALUE;
  123. }
  124. found = unicode_find(/*path,*/ zz, out, out_ptr, 1, &f);
  125. }
  126. free(zz);
  127. *ptr = bk;
  128. if (f != INVALID_HANDLE_VALUE) FindClose(f);
  129. return found;
  130. }
  131. return 0;
  132. }
  133. void CreateFile_HACK(const char * path, wchar_t out[FILENAME_SIZE])
  134. {
  135. MultiByteToWideChar(CP_ACP, 0, path, -1, out, FILENAME_SIZE);
  136. if (PathIsURLW(out))
  137. return ;
  138. if (!StrChrW(out, L'?'))
  139. return ; // no unconvertables? Great!
  140. // if (PathFileExistsW(out))
  141. // return ; // no unconvertables? Great!
  142. bool found = false;
  143. memset(out, 0, FILENAME_SIZE * sizeof(wchar_t));
  144. char * _p = _strdup(path);
  145. char * t = strchr(_p, '\\');
  146. if (t)
  147. {
  148. char bk = t[1];
  149. t[1] = 0;
  150. UINT o = MultiByteToWideChar(CP_ACP, 0, _p, -1, out, FILENAME_SIZE);
  151. o--;
  152. t[1] = bk;
  153. found = unicode_open_recur(_p, t + 1, out, o);
  154. }
  155. else
  156. found = unicode_open_recur(_p, _p, out, 0);
  157. free(_p);
  158. if (!found)
  159. MultiByteToWideChar(CP_ACP, 0, path, -1, out, FILENAME_SIZE);
  160. }
  161. private:
  162. wchar_t wideFn[FILENAME_SIZE];
  163. };
  164. #pragma warning(pop)
  165. #ifdef REMOVE_FILENAME_SIZE
  166. #undef FILENAME_SIZE
  167. #endif
  168. #endif