The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1108 lines
32KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #ifdef _MSC_VER
  24. #pragma warning (disable: 4514)
  25. #pragma warning (push)
  26. #endif
  27. #include "win32_headers.h"
  28. #include "../../../src/juce_core/basics/juce_StandardHeader.h"
  29. #include <ctime>
  30. #ifndef _WIN32_IE
  31. #define _WIN32_IE 0x0400
  32. #endif
  33. #include <shlobj.h>
  34. #ifndef CSIDL_MYMUSIC
  35. #define CSIDL_MYMUSIC 0x000d
  36. #endif
  37. #ifndef CSIDL_MYVIDEO
  38. #define CSIDL_MYVIDEO 0x000e
  39. #endif
  40. BEGIN_JUCE_NAMESPACE
  41. #include "../../../src/juce_core/io/files/juce_File.h"
  42. #include "../../../src/juce_core/io/network/juce_URL.h"
  43. #include "../../../src/juce_core/basics/juce_SystemStats.h"
  44. #include "../../../src/juce_core/io/files/juce_NamedPipe.h"
  45. #include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
  46. #ifdef _MSC_VER
  47. #pragma warning (pop)
  48. #endif
  49. //==============================================================================
  50. const tchar File::separator = T('\\');
  51. const tchar* File::separatorString = T("\\");
  52. //==============================================================================
  53. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  54. UNICODE_FUNCTION (GetFileAttributesW, DWORD, (LPCWSTR))
  55. UNICODE_FUNCTION (GetFileAttributesExW, BOOL, (LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID))
  56. UNICODE_FUNCTION (SetFileAttributesW, BOOL, (LPCWSTR, DWORD))
  57. UNICODE_FUNCTION (RemoveDirectoryW, BOOL, (LPCWSTR))
  58. UNICODE_FUNCTION (DeleteFileW, BOOL, (LPCWSTR))
  59. UNICODE_FUNCTION (MoveFileW, BOOL, (LPCWSTR, LPCWSTR))
  60. UNICODE_FUNCTION (CopyFileW, BOOL, (LPCWSTR, LPCWSTR, BOOL))
  61. UNICODE_FUNCTION (CreateDirectoryW, BOOL, (LPCWSTR, LPSECURITY_ATTRIBUTES))
  62. UNICODE_FUNCTION (CreateFileW, HANDLE, (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE))
  63. UNICODE_FUNCTION (CreateNamedPipeW, HANDLE, (LPCWSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPSECURITY_ATTRIBUTES))
  64. UNICODE_FUNCTION (GetTempPathW, DWORD, (DWORD, LPCWSTR))
  65. UNICODE_FUNCTION (SHGetSpecialFolderPathW, BOOL, (HWND, LPCWSTR, int, BOOL))
  66. UNICODE_FUNCTION (GetModuleFileNameW, DWORD, (HMODULE, LPCWSTR, DWORD))
  67. UNICODE_FUNCTION (GetCurrentDirectoryW, DWORD, (DWORD, LPCWSTR))
  68. UNICODE_FUNCTION (SetCurrentDirectoryW, BOOL, (LPCWSTR))
  69. UNICODE_FUNCTION (FindFirstFileW, HANDLE, (LPCWSTR, LPWIN32_FIND_DATAW))
  70. UNICODE_FUNCTION (FindNextFileW, BOOL, (HANDLE, LPWIN32_FIND_DATAW))
  71. void juce_initialiseUnicodeFileFunctions() throw()
  72. {
  73. static_jassert (CSIDL_MYMUSIC == 0x000d);
  74. static_jassert (CSIDL_MYVIDEO == 0x000e);
  75. if ((SystemStats::getOperatingSystemType() & SystemStats::WindowsNT) != 0)
  76. {
  77. HMODULE h = GetModuleHandleA ("kernel32.dll");
  78. UNICODE_FUNCTION_LOAD (GetFileAttributesW)
  79. UNICODE_FUNCTION_LOAD (GetFileAttributesExW)
  80. UNICODE_FUNCTION_LOAD (SetFileAttributesW)
  81. UNICODE_FUNCTION_LOAD (RemoveDirectoryW)
  82. UNICODE_FUNCTION_LOAD (DeleteFileW)
  83. UNICODE_FUNCTION_LOAD (MoveFileW)
  84. UNICODE_FUNCTION_LOAD (CopyFileW)
  85. UNICODE_FUNCTION_LOAD (CreateDirectoryW)
  86. UNICODE_FUNCTION_LOAD (CreateFileW)
  87. UNICODE_FUNCTION_LOAD (CreateNamedPipeW)
  88. UNICODE_FUNCTION_LOAD (GetTempPathW)
  89. UNICODE_FUNCTION_LOAD (GetModuleFileNameW)
  90. UNICODE_FUNCTION_LOAD (GetCurrentDirectoryW)
  91. UNICODE_FUNCTION_LOAD (SetCurrentDirectoryW)
  92. UNICODE_FUNCTION_LOAD (FindFirstFileW)
  93. UNICODE_FUNCTION_LOAD (FindNextFileW)
  94. h = LoadLibraryA ("shell32.dll");
  95. UNICODE_FUNCTION_LOAD (SHGetSpecialFolderPathW)
  96. }
  97. }
  98. #endif
  99. //==============================================================================
  100. bool juce_fileExists (const String& fileName,
  101. const bool dontCountDirectories) throw()
  102. {
  103. if (fileName.isEmpty())
  104. return false;
  105. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  106. const DWORD attr = (wGetFileAttributesW != 0) ? wGetFileAttributesW (fileName)
  107. : GetFileAttributes (fileName);
  108. #else
  109. const DWORD attr = GetFileAttributesW (fileName);
  110. #endif
  111. return dontCountDirectories ? ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
  112. : (attr != 0xffffffff);
  113. }
  114. bool juce_isDirectory (const String& fileName) throw()
  115. {
  116. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  117. const DWORD attr = (wGetFileAttributesW != 0) ? wGetFileAttributesW (fileName)
  118. : GetFileAttributes (fileName);
  119. #else
  120. const DWORD attr = GetFileAttributesW (fileName);
  121. #endif
  122. return (attr != 0xffffffff)
  123. && ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
  124. }
  125. bool juce_canWriteToFile (const String& fileName) throw()
  126. {
  127. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  128. const DWORD attr = (wGetFileAttributesW != 0) ? wGetFileAttributesW (fileName)
  129. : GetFileAttributes (fileName);
  130. #else
  131. const DWORD attr = GetFileAttributesW (fileName);
  132. #endif
  133. return ((attr & FILE_ATTRIBUTE_READONLY) == 0);
  134. }
  135. bool juce_setFileReadOnly (const String& fileName,
  136. bool isReadOnly)
  137. {
  138. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  139. DWORD attr = (wGetFileAttributesW != 0) ? wGetFileAttributesW (fileName)
  140. : GetFileAttributes (fileName);
  141. #else
  142. DWORD attr = GetFileAttributesW (fileName);
  143. #endif
  144. if (attr == 0xffffffff)
  145. return false;
  146. if (isReadOnly != juce_canWriteToFile (fileName))
  147. return true;
  148. if (isReadOnly)
  149. attr |= FILE_ATTRIBUTE_READONLY;
  150. else
  151. attr &= ~FILE_ATTRIBUTE_READONLY;
  152. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  153. if (wSetFileAttributesW != 0)
  154. return wSetFileAttributesW (fileName, attr) != FALSE;
  155. return SetFileAttributes (fileName, attr) != FALSE;
  156. #else
  157. return SetFileAttributesW (fileName, attr) != FALSE;
  158. #endif
  159. }
  160. //==============================================================================
  161. bool juce_deleteFile (const String& fileName) throw()
  162. {
  163. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  164. if (juce_isDirectory (fileName))
  165. return (wRemoveDirectoryW != 0) ? wRemoveDirectoryW (fileName) != 0
  166. : RemoveDirectory (fileName) != 0;
  167. else
  168. return (wDeleteFileW != 0) ? wDeleteFileW (fileName) != 0
  169. : DeleteFile (fileName) != 0;
  170. #else
  171. if (juce_isDirectory (fileName))
  172. return RemoveDirectoryW (fileName) != 0;
  173. return DeleteFileW (fileName) != 0;
  174. #endif
  175. }
  176. bool juce_moveFile (const String& source, const String& dest) throw()
  177. {
  178. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  179. return (wMoveFileW != 0) ? wMoveFileW (source, dest) != 0
  180. : MoveFile (source, dest) != 0;
  181. #else
  182. return MoveFileW (source, dest) != 0;
  183. #endif
  184. }
  185. bool juce_copyFile (const String& source, const String& dest) throw()
  186. {
  187. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  188. return (wCopyFileW != 0) ? wCopyFileW (source, dest, false) != 0
  189. : CopyFile (source, dest, false) != 0;
  190. #else
  191. return CopyFileW (source, dest, false) != 0;
  192. #endif
  193. }
  194. void juce_createDirectory (const String& fileName) throw()
  195. {
  196. if (! juce_fileExists (fileName, true))
  197. {
  198. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  199. if (wCreateDirectoryW != 0)
  200. wCreateDirectoryW (fileName, 0);
  201. else
  202. CreateDirectory (fileName, 0);
  203. #else
  204. CreateDirectoryW (fileName, 0);
  205. #endif
  206. }
  207. }
  208. //==============================================================================
  209. // return 0 if not possible
  210. void* juce_fileOpen (const String& fileName, bool forWriting) throw()
  211. {
  212. HANDLE h;
  213. if (forWriting)
  214. {
  215. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  216. if (wCreateFileW != 0)
  217. h = wCreateFileW (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
  218. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  219. else
  220. h = CreateFile (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
  221. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  222. #else
  223. h = CreateFileW (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
  224. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  225. #endif
  226. if (h != INVALID_HANDLE_VALUE)
  227. SetFilePointer (h, 0, 0, FILE_END);
  228. else
  229. h = 0;
  230. }
  231. else
  232. {
  233. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  234. if (wCreateFileW != 0)
  235. h = wCreateFileW (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
  236. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
  237. else
  238. h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
  239. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
  240. #else
  241. h = CreateFileW (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
  242. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
  243. #endif
  244. if (h == INVALID_HANDLE_VALUE)
  245. h = 0;
  246. }
  247. return (void*) h;
  248. }
  249. void juce_fileClose (void* handle) throw()
  250. {
  251. CloseHandle (handle);
  252. }
  253. //==============================================================================
  254. int juce_fileRead (void* handle, void* buffer, int size) throw()
  255. {
  256. DWORD num = 0;
  257. ReadFile ((HANDLE) handle, buffer, size, &num, 0);
  258. return num;
  259. }
  260. int juce_fileWrite (void* handle, const void* buffer, int size) throw()
  261. {
  262. DWORD num;
  263. WriteFile ((HANDLE) handle,
  264. buffer, size,
  265. &num, 0);
  266. return num;
  267. }
  268. int64 juce_fileSetPosition (void* handle, int64 pos) throw()
  269. {
  270. LARGE_INTEGER li;
  271. li.QuadPart = pos;
  272. li.LowPart = SetFilePointer ((HANDLE) handle,
  273. li.LowPart,
  274. &li.HighPart,
  275. FILE_BEGIN); // (returns -1 if it fails)
  276. return li.QuadPart;
  277. }
  278. int64 juce_fileGetPosition (void* handle) throw()
  279. {
  280. LARGE_INTEGER li;
  281. li.QuadPart = 0;
  282. li.LowPart = SetFilePointer ((HANDLE) handle,
  283. 0, &li.HighPart,
  284. FILE_CURRENT); // (returns -1 if it fails)
  285. return jmax ((int64) 0, li.QuadPart);
  286. }
  287. void juce_fileFlush (void* handle) throw()
  288. {
  289. FlushFileBuffers ((HANDLE) handle);
  290. }
  291. int64 juce_getFileSize (const String& fileName) throw()
  292. {
  293. WIN32_FILE_ATTRIBUTE_DATA attributes;
  294. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  295. if (wGetFileAttributesExW != 0 ? wGetFileAttributesExW (fileName, GetFileExInfoStandard, &attributes)
  296. : GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes))
  297. #else
  298. if (GetFileAttributesExW (fileName, GetFileExInfoStandard, &attributes))
  299. #endif
  300. {
  301. return (((int64) attributes.nFileSizeHigh) << 32)
  302. | attributes.nFileSizeLow;
  303. }
  304. return 0;
  305. }
  306. //==============================================================================
  307. static int64 fileTimeToTime (const FILETIME* const ft) throw()
  308. {
  309. // tell me if this fails!
  310. static_jassert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME));
  311. #if JUCE_GCC
  312. return (((const ULARGE_INTEGER*) ft)->QuadPart - 116444736000000000LL) / 10000;
  313. #else
  314. return (((const ULARGE_INTEGER*) ft)->QuadPart - 116444736000000000) / 10000;
  315. #endif
  316. }
  317. static void timeToFileTime (const int64 time, FILETIME* const ft) throw()
  318. {
  319. #if JUCE_GCC
  320. ((ULARGE_INTEGER*) ft)->QuadPart = time * 10000 + 116444736000000000LL;
  321. #else
  322. ((ULARGE_INTEGER*) ft)->QuadPart = time * 10000 + 116444736000000000;
  323. #endif
  324. }
  325. void juce_getFileTimes (const String& fileName,
  326. int64& modificationTime,
  327. int64& accessTime,
  328. int64& creationTime) throw()
  329. {
  330. WIN32_FILE_ATTRIBUTE_DATA attributes;
  331. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  332. if (wGetFileAttributesExW != 0 ? wGetFileAttributesExW (fileName, GetFileExInfoStandard, &attributes)
  333. : GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes))
  334. #else
  335. if (GetFileAttributesExW (fileName, GetFileExInfoStandard, &attributes))
  336. #endif
  337. {
  338. modificationTime = fileTimeToTime (&attributes.ftLastWriteTime);
  339. creationTime = fileTimeToTime (&attributes.ftCreationTime);
  340. accessTime = fileTimeToTime (&attributes.ftLastAccessTime);
  341. }
  342. else
  343. {
  344. creationTime = accessTime = modificationTime = 0;
  345. }
  346. }
  347. bool juce_setFileTimes (const String& fileName,
  348. int64 modificationTime,
  349. int64 accessTime,
  350. int64 creationTime) throw()
  351. {
  352. FILETIME m, a, c;
  353. if (modificationTime > 0)
  354. timeToFileTime (modificationTime, &m);
  355. if (accessTime > 0)
  356. timeToFileTime (accessTime, &a);
  357. if (creationTime > 0)
  358. timeToFileTime (creationTime, &c);
  359. void* const h = juce_fileOpen (fileName, true);
  360. bool ok = false;
  361. if (h != 0)
  362. {
  363. ok = SetFileTime ((HANDLE) h,
  364. (creationTime > 0) ? &c : 0,
  365. (accessTime > 0) ? &a : 0,
  366. (modificationTime > 0) ? &m : 0) != 0;
  367. juce_fileClose (h);
  368. }
  369. return ok;
  370. }
  371. //==============================================================================
  372. // return '\0' separated list of strings
  373. const StringArray juce_getFileSystemRoots() throw()
  374. {
  375. TCHAR buffer [2048];
  376. buffer[0] = 0;
  377. buffer[1] = 0;
  378. GetLogicalDriveStrings (2048, buffer);
  379. TCHAR* n = buffer;
  380. StringArray roots;
  381. while (*n != 0)
  382. {
  383. roots.add (String (n));
  384. while (*n++ != 0)
  385. {
  386. }
  387. }
  388. roots.sort (true);
  389. return roots;
  390. }
  391. //==============================================================================
  392. const String juce_getVolumeLabel (const String& filenameOnVolume,
  393. int& volumeSerialNumber) throw()
  394. {
  395. TCHAR n [4];
  396. n[0] = *(const TCHAR*) filenameOnVolume;
  397. n[1] = L':';
  398. n[2] = L'\\';
  399. n[3] = 0;
  400. TCHAR dest [64];
  401. DWORD serialNum;
  402. if (! GetVolumeInformation (n, dest, 64, (DWORD*) &serialNum, 0, 0, 0, 0))
  403. {
  404. dest[0] = 0;
  405. serialNum = 0;
  406. }
  407. volumeSerialNumber = serialNum;
  408. return String (dest);
  409. }
  410. int64 File::getBytesFreeOnVolume() const throw()
  411. {
  412. String fn (getFullPathName());
  413. if (fn[1] == T(':'))
  414. fn = fn.substring (0, 2) + T("\\");
  415. ULARGE_INTEGER spc;
  416. ULARGE_INTEGER tot;
  417. ULARGE_INTEGER totFree;
  418. if (GetDiskFreeSpaceEx (fn, &spc, &tot, &totFree))
  419. return (int64)(spc.QuadPart);
  420. return 0;
  421. }
  422. //==============================================================================
  423. static unsigned int getWindowsDriveType (const String& fileName) throw()
  424. {
  425. TCHAR n[4];
  426. n[0] = *(const TCHAR*) fileName;
  427. n[1] = L':';
  428. n[2] = L'\\';
  429. n[3] = 0;
  430. return GetDriveType (n);
  431. }
  432. bool File::isOnCDRomDrive() const throw()
  433. {
  434. return getWindowsDriveType (getFullPathName()) == DRIVE_CDROM;
  435. }
  436. bool File::isOnHardDisk() const throw()
  437. {
  438. if (fullPath.isEmpty())
  439. return false;
  440. const unsigned int n = getWindowsDriveType (getFullPathName());
  441. if (fullPath.toLowerCase()[0] <= 'b'
  442. && fullPath[1] == T(':'))
  443. {
  444. return n != DRIVE_REMOVABLE;
  445. }
  446. else
  447. {
  448. return n != DRIVE_CDROM && n != DRIVE_REMOTE;
  449. }
  450. }
  451. bool File::isOnRemovableDrive() const throw()
  452. {
  453. if (fullPath.isEmpty())
  454. return false;
  455. const unsigned int n = getWindowsDriveType (getFullPathName());
  456. return n == DRIVE_CDROM
  457. || n == DRIVE_REMOTE
  458. || n == DRIVE_REMOVABLE
  459. || n == DRIVE_RAMDISK;
  460. }
  461. //==============================================================================
  462. #define MAX_PATH_CHARS (MAX_PATH + 256)
  463. static const File juce_getSpecialFolderPath (int type) throw()
  464. {
  465. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  466. if (wSHGetSpecialFolderPathW != 0)
  467. {
  468. WCHAR path [MAX_PATH_CHARS];
  469. if (wSHGetSpecialFolderPathW (0, path, type, 0))
  470. return File (String (path));
  471. }
  472. else
  473. {
  474. TCHAR path [MAX_PATH_CHARS];
  475. if (SHGetSpecialFolderPath (0, path, type, 0))
  476. return File (String (path));
  477. }
  478. #else
  479. WCHAR path [MAX_PATH_CHARS];
  480. if (SHGetSpecialFolderPathW (0, path, type, 0))
  481. return File (String (path));
  482. #endif
  483. return File::nonexistent;
  484. }
  485. const File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type)
  486. {
  487. int csidlType = 0;
  488. switch (type)
  489. {
  490. case userHomeDirectory:
  491. case userDocumentsDirectory:
  492. csidlType = CSIDL_PERSONAL;
  493. break;
  494. case userDesktopDirectory:
  495. csidlType = CSIDL_DESKTOP;
  496. break;
  497. case userApplicationDataDirectory:
  498. csidlType = CSIDL_APPDATA;
  499. break;
  500. case commonApplicationDataDirectory:
  501. csidlType = CSIDL_COMMON_APPDATA;
  502. break;
  503. case globalApplicationsDirectory:
  504. csidlType = CSIDL_PROGRAM_FILES;
  505. break;
  506. case userMusicDirectory:
  507. csidlType = CSIDL_MYMUSIC;
  508. break;
  509. case userMoviesDirectory:
  510. csidlType = CSIDL_MYVIDEO;
  511. break;
  512. case tempDirectory:
  513. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  514. if (wGetTempPathW != 0)
  515. {
  516. WCHAR dest [2048];
  517. dest[0] = 0;
  518. wGetTempPathW (2048, dest);
  519. return File (String (dest));
  520. }
  521. else
  522. {
  523. TCHAR dest [2048];
  524. dest[0] = 0;
  525. GetTempPath (2048, dest);
  526. return File (String (dest));
  527. }
  528. #else
  529. {
  530. WCHAR dest [2048];
  531. dest[0] = 0;
  532. GetTempPathW (2048, dest);
  533. return File (String (dest));
  534. }
  535. #endif
  536. case currentExecutableFile:
  537. case currentApplicationFile:
  538. {
  539. HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle();
  540. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  541. if (wGetModuleFileNameW != 0)
  542. {
  543. WCHAR dest [MAX_PATH_CHARS];
  544. dest[0] = 0;
  545. wGetModuleFileNameW (moduleHandle, dest, MAX_PATH_CHARS);
  546. return File (String (dest));
  547. }
  548. else
  549. {
  550. TCHAR dest [MAX_PATH_CHARS];
  551. dest[0] = 0;
  552. GetModuleFileName (moduleHandle, dest, MAX_PATH_CHARS);
  553. return File (String (dest));
  554. }
  555. #else
  556. WCHAR dest [MAX_PATH_CHARS];
  557. dest[0] = 0;
  558. GetModuleFileNameW (moduleHandle, dest, MAX_PATH_CHARS);
  559. return File (String (dest));
  560. #endif
  561. }
  562. break;
  563. default:
  564. jassertfalse // unknown type?
  565. return File::nonexistent;
  566. }
  567. return juce_getSpecialFolderPath (csidlType);
  568. }
  569. void juce_setCurrentExecutableFileName (const String&) throw()
  570. {
  571. // n/a on windows
  572. }
  573. //==============================================================================
  574. const File File::getCurrentWorkingDirectory() throw()
  575. {
  576. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  577. if (wGetCurrentDirectoryW != 0)
  578. {
  579. WCHAR dest [MAX_PATH_CHARS];
  580. dest[0] = 0;
  581. wGetCurrentDirectoryW (MAX_PATH_CHARS, dest);
  582. return File (String (dest));
  583. }
  584. else
  585. {
  586. TCHAR dest [MAX_PATH_CHARS];
  587. dest[0] = 0;
  588. GetCurrentDirectory (MAX_PATH_CHARS, dest);
  589. return File (String (dest));
  590. }
  591. #else
  592. WCHAR dest [MAX_PATH_CHARS];
  593. dest[0] = 0;
  594. GetCurrentDirectoryW (MAX_PATH_CHARS, dest);
  595. return File (String (dest));
  596. #endif
  597. }
  598. bool File::setAsCurrentWorkingDirectory() const throw()
  599. {
  600. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  601. return (wSetCurrentDirectoryW != 0) ? wSetCurrentDirectoryW (getFullPathName()) != FALSE
  602. : SetCurrentDirectory (getFullPathName()) != FALSE;
  603. #else
  604. return SetCurrentDirectoryW (getFullPathName()) != FALSE;
  605. #endif
  606. }
  607. //==============================================================================
  608. template <class FindDataType>
  609. static void getFindFileInfo (FindDataType& findData,
  610. String& filename, bool* const isDir, bool* const isHidden,
  611. int64* const fileSize, Time* const modTime, Time* const creationTime,
  612. bool* const isReadOnly) throw()
  613. {
  614. filename = findData.cFileName;
  615. if (isDir != 0)
  616. *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
  617. if (isHidden != 0)
  618. *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
  619. if (fileSize != 0)
  620. *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
  621. if (modTime != 0)
  622. *modTime = fileTimeToTime (&findData.ftLastWriteTime);
  623. if (creationTime != 0)
  624. *creationTime = fileTimeToTime (&findData.ftCreationTime);
  625. if (isReadOnly != 0)
  626. *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
  627. }
  628. void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResult,
  629. bool* isDir, bool* isHidden, int64* fileSize,
  630. Time* modTime, Time* creationTime, bool* isReadOnly) throw()
  631. {
  632. String wc (directory);
  633. if (! wc.endsWithChar (File::separator))
  634. wc += File::separator;
  635. wc += wildCard;
  636. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  637. if (wFindFirstFileW != 0)
  638. {
  639. WIN32_FIND_DATAW findData;
  640. HANDLE h = wFindFirstFileW (wc, &findData);
  641. if (h != INVALID_HANDLE_VALUE)
  642. {
  643. getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  644. return h;
  645. }
  646. }
  647. else
  648. {
  649. WIN32_FIND_DATA findData;
  650. HANDLE h = FindFirstFile (wc, &findData);
  651. if (h != INVALID_HANDLE_VALUE)
  652. {
  653. getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  654. return h;
  655. }
  656. }
  657. #else
  658. WIN32_FIND_DATAW findData;
  659. HANDLE h = FindFirstFileW (wc, &findData);
  660. if (h != INVALID_HANDLE_VALUE)
  661. {
  662. getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  663. return h;
  664. }
  665. #endif
  666. firstResult = String::empty;
  667. return 0;
  668. }
  669. bool juce_findFileNext (void* handle, String& resultFile,
  670. bool* isDir, bool* isHidden, int64* fileSize,
  671. Time* modTime, Time* creationTime, bool* isReadOnly) throw()
  672. {
  673. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  674. if (wFindNextFileW != 0)
  675. {
  676. WIN32_FIND_DATAW findData;
  677. if (handle != 0 && wFindNextFileW ((HANDLE) handle, &findData) != 0)
  678. {
  679. getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  680. return true;
  681. }
  682. }
  683. else
  684. {
  685. WIN32_FIND_DATA findData;
  686. if (handle != 0 && FindNextFile ((HANDLE) handle, &findData) != 0)
  687. {
  688. getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  689. return true;
  690. }
  691. }
  692. #else
  693. WIN32_FIND_DATAW findData;
  694. if (handle != 0 && FindNextFileW ((HANDLE) handle, &findData) != 0)
  695. {
  696. getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  697. return true;
  698. }
  699. #endif
  700. resultFile = String::empty;
  701. return false;
  702. }
  703. void juce_findFileClose (void* handle) throw()
  704. {
  705. FindClose (handle);
  706. }
  707. //==============================================================================
  708. bool juce_launchFile (const String& fileName,
  709. const String& parameters) throw()
  710. {
  711. HINSTANCE hInstance = 0;
  712. JUCE_TRY
  713. {
  714. hInstance = ShellExecute (0, 0, fileName, parameters, 0, SW_SHOWDEFAULT);
  715. }
  716. JUCE_CATCH_ALL
  717. return hInstance > (HINSTANCE) 32;
  718. }
  719. //==============================================================================
  720. struct NamedPipeInternal
  721. {
  722. HANDLE pipeH;
  723. HANDLE cancelEvent;
  724. bool connected, createdPipe;
  725. NamedPipeInternal()
  726. : pipeH (0),
  727. cancelEvent (0),
  728. connected (false),
  729. createdPipe (false)
  730. {
  731. cancelEvent = CreateEvent (0, FALSE, FALSE, 0);
  732. }
  733. ~NamedPipeInternal()
  734. {
  735. disconnect();
  736. if (pipeH != 0)
  737. CloseHandle (pipeH);
  738. CloseHandle (cancelEvent);
  739. }
  740. bool connect (const int timeOutMs)
  741. {
  742. if (! createdPipe)
  743. return true;
  744. if (! connected)
  745. {
  746. OVERLAPPED over;
  747. zerostruct (over);
  748. over.hEvent = CreateEvent (0, TRUE, FALSE, 0);
  749. if (ConnectNamedPipe (pipeH, &over))
  750. {
  751. connected = false; // yes, you read that right. In overlapped mode it should always return 0.
  752. }
  753. else
  754. {
  755. const int err = GetLastError();
  756. if (err == ERROR_IO_PENDING || err == ERROR_PIPE_LISTENING)
  757. {
  758. HANDLE handles[] = { over.hEvent, cancelEvent };
  759. if (WaitForMultipleObjects (2, handles, FALSE,
  760. timeOutMs >= 0 ? timeOutMs : INFINITE) == WAIT_OBJECT_0)
  761. connected = true;
  762. }
  763. else if (err == ERROR_PIPE_CONNECTED)
  764. {
  765. connected = true;
  766. }
  767. }
  768. CloseHandle (over.hEvent);
  769. }
  770. return connected;
  771. }
  772. void disconnect()
  773. {
  774. if (connected)
  775. {
  776. DisconnectNamedPipe (pipeH);
  777. connected = false;
  778. }
  779. }
  780. };
  781. void NamedPipe::close()
  782. {
  783. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  784. delete intern;
  785. internal = 0;
  786. }
  787. bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
  788. {
  789. close();
  790. NamedPipeInternal* const intern = new NamedPipeInternal();
  791. String file ("\\\\.\\pipe\\");
  792. file += pipeName;
  793. intern->createdPipe = createPipe;
  794. if (createPipe)
  795. {
  796. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  797. if (wCreateNamedPipeW != 0)
  798. intern->pipeH = wCreateNamedPipeW (file, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
  799. 1, 64, 64, 0, NULL);
  800. else
  801. intern->pipeH = CreateNamedPipe (file, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
  802. 1, 64, 64, 0, NULL);
  803. #else
  804. intern->pipeH = CreateNamedPipeW (file, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0,
  805. 1, 64, 64, 0, NULL);
  806. #endif
  807. }
  808. else
  809. {
  810. #if JUCE_ENABLE_WIN98_COMPATIBILITY
  811. if (wCreateFileW != 0)
  812. intern->pipeH = wCreateFileW (file, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
  813. FILE_FLAG_OVERLAPPED, 0);
  814. else
  815. intern->pipeH = CreateFile (file, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
  816. FILE_FLAG_OVERLAPPED, 0);
  817. #else
  818. intern->pipeH = CreateFileW (file, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
  819. FILE_FLAG_OVERLAPPED, 0);
  820. #endif
  821. }
  822. if (intern->pipeH != INVALID_HANDLE_VALUE)
  823. {
  824. internal = intern;
  825. return true;
  826. }
  827. delete intern;
  828. return false;
  829. }
  830. int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds)
  831. {
  832. int bytesRead = -1;
  833. bool waitAgain = true;
  834. while (waitAgain && internal != 0)
  835. {
  836. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  837. waitAgain = false;
  838. if (! intern->connect (timeOutMilliseconds))
  839. break;
  840. if (maxBytesToRead <= 0)
  841. return 0;
  842. OVERLAPPED over;
  843. zerostruct (over);
  844. over.hEvent = CreateEvent (0, TRUE, FALSE, 0);
  845. unsigned long numRead;
  846. if (ReadFile (intern->pipeH, destBuffer, maxBytesToRead, &numRead, &over))
  847. {
  848. bytesRead = (int) numRead;
  849. }
  850. else if (GetLastError() == ERROR_IO_PENDING)
  851. {
  852. HANDLE handles[] = { over.hEvent, intern->cancelEvent };
  853. if (WaitForMultipleObjects (2, handles, FALSE,
  854. timeOutMilliseconds >= 0 ? timeOutMilliseconds
  855. : INFINITE) == WAIT_OBJECT_0)
  856. {
  857. if (GetOverlappedResult (intern->pipeH, &over, &numRead, FALSE))
  858. {
  859. bytesRead = (int) numRead;
  860. }
  861. else if (GetLastError() == ERROR_BROKEN_PIPE && intern->createdPipe)
  862. {
  863. intern->disconnect();
  864. waitAgain = true;
  865. }
  866. }
  867. }
  868. else
  869. {
  870. waitAgain = internal != 0;
  871. Sleep (5);
  872. }
  873. CloseHandle (over.hEvent);
  874. }
  875. return bytesRead;
  876. }
  877. int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds)
  878. {
  879. int bytesWritten = -1;
  880. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  881. if (intern != 0 && intern->connect (timeOutMilliseconds))
  882. {
  883. if (numBytesToWrite <= 0)
  884. return 0;
  885. OVERLAPPED over;
  886. zerostruct (over);
  887. over.hEvent = CreateEvent (0, TRUE, FALSE, 0);
  888. unsigned long numWritten;
  889. if (WriteFile (intern->pipeH, sourceBuffer, numBytesToWrite, &numWritten, &over))
  890. {
  891. bytesWritten = (int) numWritten;
  892. }
  893. else if (GetLastError() == ERROR_IO_PENDING)
  894. {
  895. HANDLE handles[] = { over.hEvent, intern->cancelEvent };
  896. if (WaitForMultipleObjects (2, handles, FALSE, timeOutMilliseconds >= 0 ? timeOutMilliseconds
  897. : INFINITE) == WAIT_OBJECT_0)
  898. {
  899. if (GetOverlappedResult (intern->pipeH, &over, &numWritten, FALSE))
  900. {
  901. bytesWritten = (int) numWritten;
  902. }
  903. else if (GetLastError() == ERROR_BROKEN_PIPE && intern->createdPipe)
  904. {
  905. intern->disconnect();
  906. }
  907. }
  908. }
  909. CloseHandle (over.hEvent);
  910. }
  911. return bytesWritten;
  912. }
  913. void NamedPipe::cancelPendingReads()
  914. {
  915. NamedPipeInternal* const intern = (NamedPipeInternal*) internal;
  916. if (intern != 0)
  917. SetEvent (intern->cancelEvent);
  918. }
  919. END_JUCE_NAMESPACE