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.

482 lines
16KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. // (This file gets included by juce_win32_NativeCode.cpp, rather than being
  19. // compiled on its own).
  20. #if JUCE_INCLUDED_FILE
  21. #ifndef INTERNET_FLAG_NEED_FILE
  22. #define INTERNET_FLAG_NEED_FILE 0x00000010
  23. #endif
  24. #ifndef INTERNET_OPTION_DISABLE_AUTODIAL
  25. #define INTERNET_OPTION_DISABLE_AUTODIAL 70
  26. #endif
  27. //==============================================================================
  28. bool juce_isOnLine()
  29. {
  30. DWORD connectionType;
  31. return InternetGetConnectedState (&connectionType, 0) != 0
  32. || (connectionType & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_PROXY)) != 0;
  33. }
  34. struct ConnectionAndRequestStruct
  35. {
  36. HINTERNET connection, request;
  37. };
  38. static HINTERNET sessionHandle = 0;
  39. #ifndef WORKAROUND_TIMEOUT_BUG
  40. //#define WORKAROUND_TIMEOUT_BUG 1
  41. #endif
  42. #if WORKAROUND_TIMEOUT_BUG
  43. // Required because of a Microsoft bug in setting a timeout
  44. class InternetConnectThread : public Thread
  45. {
  46. public:
  47. InternetConnectThread (URL_COMPONENTS& uc_, HINTERNET& connection_, const bool isFtp_)
  48. : Thread ("Internet"), uc (uc_), connection (connection_), isFtp (isFtp_)
  49. {
  50. startThread();
  51. }
  52. ~InternetConnectThread()
  53. {
  54. stopThread (60000);
  55. }
  56. void run()
  57. {
  58. connection = InternetConnect (sessionHandle, uc.lpszHostName,
  59. uc.nPort, _T(""), _T(""),
  60. isFtp ? INTERNET_SERVICE_FTP
  61. : INTERNET_SERVICE_HTTP,
  62. 0, 0);
  63. notify();
  64. }
  65. juce_UseDebuggingNewOperator
  66. private:
  67. URL_COMPONENTS& uc;
  68. HINTERNET& connection;
  69. const bool isFtp;
  70. InternetConnectThread (const InternetConnectThread&);
  71. InternetConnectThread& operator= (const InternetConnectThread&);
  72. };
  73. #endif
  74. void* juce_openInternetFile (const String& url,
  75. const String& headers,
  76. const MemoryBlock& postData,
  77. const bool isPost,
  78. URL::OpenStreamProgressCallback* callback,
  79. void* callbackContext,
  80. int timeOutMs)
  81. {
  82. if (sessionHandle == 0)
  83. sessionHandle = InternetOpen (_T("juce"),
  84. INTERNET_OPEN_TYPE_PRECONFIG,
  85. 0, 0, 0);
  86. if (sessionHandle != 0)
  87. {
  88. // break up the url..
  89. TCHAR file[1024], server[1024];
  90. URL_COMPONENTS uc;
  91. zerostruct (uc);
  92. uc.dwStructSize = sizeof (uc);
  93. uc.dwUrlPathLength = sizeof (file);
  94. uc.dwHostNameLength = sizeof (server);
  95. uc.lpszUrlPath = file;
  96. uc.lpszHostName = server;
  97. if (InternetCrackUrl (url, 0, 0, &uc))
  98. {
  99. int disable = 1;
  100. InternetSetOption (sessionHandle, INTERNET_OPTION_DISABLE_AUTODIAL, &disable, sizeof (disable));
  101. if (timeOutMs == 0)
  102. timeOutMs = 30000;
  103. else if (timeOutMs < 0)
  104. timeOutMs = -1;
  105. InternetSetOption (sessionHandle, INTERNET_OPTION_CONNECT_TIMEOUT, &timeOutMs, sizeof (timeOutMs));
  106. const bool isFtp = url.startsWithIgnoreCase (T("ftp:"));
  107. #if WORKAROUND_TIMEOUT_BUG
  108. HINTERNET connection = 0;
  109. {
  110. InternetConnectThread connectThread (uc, connection, isFtp);
  111. connectThread.wait (timeOutMs);
  112. if (connection == 0)
  113. {
  114. InternetCloseHandle (sessionHandle);
  115. sessionHandle = 0;
  116. }
  117. }
  118. #else
  119. HINTERNET connection = InternetConnect (sessionHandle,
  120. uc.lpszHostName,
  121. uc.nPort,
  122. _T(""), _T(""),
  123. isFtp ? INTERNET_SERVICE_FTP
  124. : INTERNET_SERVICE_HTTP,
  125. 0, 0);
  126. #endif
  127. if (connection != 0)
  128. {
  129. if (isFtp)
  130. {
  131. HINTERNET request = FtpOpenFile (connection,
  132. uc.lpszUrlPath,
  133. GENERIC_READ,
  134. FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_NEED_FILE,
  135. 0);
  136. ConnectionAndRequestStruct* const result = new ConnectionAndRequestStruct();
  137. result->connection = connection;
  138. result->request = request;
  139. return result;
  140. }
  141. else
  142. {
  143. const TCHAR* mimeTypes[] = { _T("*/*"), 0 };
  144. DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE;
  145. if (url.startsWithIgnoreCase (T("https:")))
  146. flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 -
  147. // IE7 seems to automatically work out when it's https)
  148. HINTERNET request = HttpOpenRequest (connection,
  149. isPost ? _T("POST")
  150. : _T("GET"),
  151. uc.lpszUrlPath,
  152. 0, 0, mimeTypes, flags, 0);
  153. if (request != 0)
  154. {
  155. INTERNET_BUFFERS buffers;
  156. zerostruct (buffers);
  157. buffers.dwStructSize = sizeof (INTERNET_BUFFERS);
  158. buffers.lpcszHeader = (LPCTSTR) headers;
  159. buffers.dwHeadersLength = headers.length();
  160. buffers.dwBufferTotal = (DWORD) postData.getSize();
  161. ConnectionAndRequestStruct* result = 0;
  162. if (HttpSendRequestEx (request, &buffers, 0, HSR_INITIATE, 0))
  163. {
  164. int bytesSent = 0;
  165. for (;;)
  166. {
  167. const int bytesToDo = jmin (1024, (int) postData.getSize() - bytesSent);
  168. DWORD bytesDone = 0;
  169. if (bytesToDo > 0
  170. && ! InternetWriteFile (request,
  171. ((const char*) postData.getData()) + bytesSent,
  172. bytesToDo, &bytesDone))
  173. {
  174. break;
  175. }
  176. if (bytesToDo == 0 || (int) bytesDone < bytesToDo)
  177. {
  178. result = new ConnectionAndRequestStruct();
  179. result->connection = connection;
  180. result->request = request;
  181. HttpEndRequest (request, 0, 0, 0);
  182. return result;
  183. }
  184. bytesSent += bytesDone;
  185. if (callback != 0 && ! callback (callbackContext, bytesSent, postData.getSize()))
  186. break;
  187. }
  188. }
  189. InternetCloseHandle (request);
  190. }
  191. InternetCloseHandle (connection);
  192. }
  193. }
  194. }
  195. }
  196. return 0;
  197. }
  198. int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
  199. {
  200. DWORD bytesRead = 0;
  201. const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
  202. if (crs != 0)
  203. InternetReadFile (crs->request,
  204. buffer, bytesToRead,
  205. &bytesRead);
  206. return bytesRead;
  207. }
  208. int juce_seekInInternetFile (void* handle, int newPosition)
  209. {
  210. if (handle != 0)
  211. {
  212. const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
  213. return InternetSetFilePointer (crs->request,
  214. newPosition, 0,
  215. FILE_BEGIN, 0);
  216. }
  217. else
  218. {
  219. return -1;
  220. }
  221. }
  222. int64 juce_getInternetFileContentLength (void* handle)
  223. {
  224. const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
  225. if (crs != 0)
  226. {
  227. DWORD index = 0;
  228. DWORD result = 0;
  229. DWORD size = sizeof (result);
  230. if (HttpQueryInfo (crs->request,
  231. HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
  232. &result,
  233. &size,
  234. &index))
  235. {
  236. return (int64) result;
  237. }
  238. }
  239. return -1;
  240. }
  241. void juce_closeInternetFile (void* handle)
  242. {
  243. if (handle != 0)
  244. {
  245. ConnectionAndRequestStruct* const crs = (ConnectionAndRequestStruct*) handle;
  246. InternetCloseHandle (crs->request);
  247. InternetCloseHandle (crs->connection);
  248. delete crs;
  249. }
  250. }
  251. //==============================================================================
  252. static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum, const bool littleEndian) throw()
  253. {
  254. int numFound = 0;
  255. DynamicLibraryLoader dll ("iphlpapi.dll");
  256. DynamicLibraryImport (GetAdaptersInfo, getAdaptersInfo, DWORD, dll, (PIP_ADAPTER_INFO, PULONG))
  257. if (getAdaptersInfo != 0)
  258. {
  259. ULONG len = sizeof (IP_ADAPTER_INFO);
  260. MemoryBlock mb;
  261. PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO) mb.getData();
  262. if (getAdaptersInfo (adapterInfo, &len) == ERROR_BUFFER_OVERFLOW)
  263. {
  264. mb.setSize (len);
  265. adapterInfo = (PIP_ADAPTER_INFO) mb.getData();
  266. }
  267. if (getAdaptersInfo (adapterInfo, &len) == NO_ERROR)
  268. {
  269. PIP_ADAPTER_INFO adapter = adapterInfo;
  270. while (adapter != 0)
  271. {
  272. int64 mac = 0;
  273. for (unsigned int i = 0; i < adapter->AddressLength; ++i)
  274. mac = (mac << 8) | adapter->Address[i];
  275. if (littleEndian)
  276. mac = (int64) ByteOrder::swap ((uint64) mac);
  277. if (numFound < maxNum && mac != 0)
  278. addresses [numFound++] = mac;
  279. adapter = adapter->Next;
  280. }
  281. }
  282. }
  283. return numFound;
  284. }
  285. struct ASTAT
  286. {
  287. ADAPTER_STATUS adapt;
  288. NAME_BUFFER NameBuff [30];
  289. };
  290. static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool littleEndian) throw()
  291. {
  292. int numFound = 0;
  293. DynamicLibraryLoader dll ("netapi32.dll");
  294. DynamicLibraryImport (Netbios, NetbiosCall, UCHAR, dll, (PNCB))
  295. if (NetbiosCall != 0)
  296. {
  297. NCB ncb;
  298. zerostruct (ncb);
  299. ASTAT astat;
  300. zerostruct (astat);
  301. LANA_ENUM enums;
  302. zerostruct (enums);
  303. ncb.ncb_command = NCBENUM;
  304. ncb.ncb_buffer = (unsigned char*) &enums;
  305. ncb.ncb_length = sizeof (LANA_ENUM);
  306. NetbiosCall (&ncb);
  307. for (int i = 0; i < enums.length; ++i)
  308. {
  309. zerostruct (ncb);
  310. ncb.ncb_command = NCBRESET;
  311. ncb.ncb_lana_num = enums.lana[i];
  312. if (NetbiosCall (&ncb) == 0)
  313. {
  314. zerostruct (ncb);
  315. memcpy (ncb.ncb_callname, "* ", NCBNAMSZ);
  316. ncb.ncb_command = NCBASTAT;
  317. ncb.ncb_lana_num = enums.lana[i];
  318. ncb.ncb_buffer = (unsigned char*) &astat;
  319. ncb.ncb_length = sizeof (ASTAT);
  320. if (NetbiosCall (&ncb) == 0)
  321. {
  322. if (astat.adapt.adapter_type == 0xfe)
  323. {
  324. uint64 mac = 0;
  325. for (int i = 6; --i >= 0;)
  326. mac = (mac << 8) | astat.adapt.adapter_address [littleEndian ? i : (5 - i)];
  327. if (numFound < maxNum && mac != 0)
  328. addresses [numFound++] = mac;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. return numFound;
  335. }
  336. int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian)
  337. {
  338. int numFound = getMACAddressViaGetAdaptersInfo (addresses, maxNum, littleEndian);
  339. if (numFound == 0)
  340. numFound = getMACAddressesViaNetBios (addresses, maxNum, littleEndian);
  341. return numFound;
  342. }
  343. //==============================================================================
  344. typedef ULONG (WINAPI *MAPISendMailType) (LHANDLE, ULONG, lpMapiMessage, ::FLAGS, ULONG);
  345. bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
  346. const String& emailSubject,
  347. const String& bodyText,
  348. const StringArray& filesToAttach)
  349. {
  350. HMODULE h = LoadLibraryA ("MAPI32.dll");
  351. MAPISendMailType mapiSendMail = (MAPISendMailType) GetProcAddress (h, "MAPISendMail");
  352. bool ok = false;
  353. if (mapiSendMail != 0)
  354. {
  355. MapiMessage message;
  356. zerostruct (message);
  357. message.lpszSubject = (LPSTR) emailSubject.toCString();
  358. message.lpszNoteText = (LPSTR) bodyText.toCString();
  359. MapiRecipDesc recip;
  360. zerostruct (recip);
  361. recip.ulRecipClass = MAPI_TO;
  362. String targetEmailAddress_ (targetEmailAddress);
  363. if (targetEmailAddress_.isEmpty())
  364. targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address)
  365. recip.lpszName = (LPSTR) targetEmailAddress_.toCString();
  366. message.nRecipCount = 1;
  367. message.lpRecips = &recip;
  368. MemoryBlock mb (sizeof (MapiFileDesc) * filesToAttach.size());
  369. mb.fillWith (0);
  370. MapiFileDesc* files = (MapiFileDesc*) mb.getData();
  371. message.nFileCount = filesToAttach.size();
  372. message.lpFiles = files;
  373. for (int i = 0; i < filesToAttach.size(); ++i)
  374. {
  375. files[i].nPosition = (ULONG) -1;
  376. files[i].lpszPathName = (LPSTR) filesToAttach[i].toCString();
  377. }
  378. ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS);
  379. }
  380. FreeLibrary (h);
  381. return ok;
  382. }
  383. #endif