ardour
msvc_pbd.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 John Emmas
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program 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 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifdef COMPILER_MSVC
21 
22 #include <WTypes.h>
23 
24 extern "C" WINBASEAPI BOOL WINAPI
25 CreateHardLinkA( LPCSTR lpFileName,
26  LPCSTR lpExistingFileName,
27  LPSECURITY_ATTRIBUTES lpSecurityAttributes ); // Needs kernel32.lib on anything higher than Win2K
28 
29 #include <algorithm>
30 #include <string>
31 #include <io.h>
32 #include <math.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <stdlib.h>
36 #include <sys/stat.h>
37 #include <pbd/error.h>
38 #include <ardourext/misc.h>
39 #include <ardourext/pthread.h> // Should ensure that we include the right
40  // version - but we'll check anyway, later
41 
42 #include <glibmm.h>
43 
44 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
45 
46 struct timezone
47 {
48  int tz_minuteswest; /* minutes W of Greenwich */
49  int tz_dsttime; /* type of dst correction */
50 };
51 
53 gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz) // Does this need to be exported ?
54 {
55 FILETIME ft;
56 unsigned __int64 tmpres = 0;
57 static int tzflag = 0;
58 
59  if (NULL != tv)
60  {
61  GetSystemTimeAsFileTime(&ft);
62 
63  tmpres |= ft.dwHighDateTime;
64  tmpres <<= 32;
65  tmpres |= ft.dwLowDateTime;
66 
67  /*converting file time to unix epoch*/
68  tmpres /= 10; /*convert into microseconds*/
69  tmpres -= DELTA_EPOCH_IN_MICROSECS;
70  tv->tv_sec = (long)(tmpres / 1000000UL);
71  tv->tv_usec = (long)(tmpres % 1000000UL);
72  }
73 
74  if (NULL != tz)
75  {
76  struct timezone *ptz = static_cast<struct timezone*> (tz);
77  if (!tzflag)
78  {
79  _tzset();
80  tzflag++;
81  }
82  if (ptz)
83  {
84  ptz->tz_minuteswest = _timezone / 60;
85  ptz->tz_dsttime = _daylight;
86  }
87  }
88 
89  return 0;
90 }
91 
92 // Define the default comparison operators for Windows (ptw32) 'pthread_t' (not used
93 // by Ardour AFAIK but would be needed if an array of 'pthread_t' had to be sorted).
94 #ifndef PTHREAD_H // Defined by PTW32 (Linux and other versions define _PTHREAD_H)
95 #error "An incompatible version of 'pthread.h' is #included. Use only the Windows (ptw32) version!"
96 #else
97 LIBPBD_API bool operator> (const pthread_t& lhs, const pthread_t& rhs)
98 {
99  return (std::greater<void*>()(lhs.p, rhs.p));
100 }
101 
102 LIBPBD_API bool operator< (const pthread_t& lhs, const pthread_t& rhs)
103 {
104  return (std::less<void*>()(lhs.p, rhs.p));
105 }
106 
107 LIBPBD_API bool operator!= (const pthread_t& lhs, const pthread_t& rhs)
108 {
109  return (std::not_equal_to<void*>()(lhs.p, rhs.p));
110 }
111 
112 LIBPBD_API bool operator== (const pthread_t& lhs, const pthread_t& rhs)
113 {
114  return (!(lhs != rhs));
115 }
116 #endif
117 
118 // Functions supplied (later) to std::transform
119 //***************************************************************
120 //
121 // invert_backslash()
122 //
123 // Examines a supplied ASCII character and (if the character is
124 // a backslash) converts it to a forward slash,
125 //
126 // Returns:
127 //
128 // The supplied character (converted, if it was a backslash)
129 //
130 char invert_backslash(char character)
131 {
132  if ('\\' == character)
133  character = '/';
134 
135  return (character);
136 }
137 
138 //***************************************************************
139 //
140 // invert_forwardslash()
141 //
142 // Examines a supplied ASCII character and (if the character is
143 // a forward slash) converts it to a backslash,
144 //
145 // Returns:
146 //
147 // The supplied character (converted, if it was a fwd slash)
148 //
149 char invert_forwardslash(char character)
150 {
151  if ('/' == character)
152  character = '\\';
153 
154  return (character);
155 }
156 
157 
158 //***************************************************************
159 //
160 // pread()
161 //
162 // Emulates pread() using _lseek()/_read()/_lseek().
163 //
164 // Returns:
165 //
166 // On Success: The number of bytes read from the file
167 // On Failure: -1
168 //
170 pread(int handle, void *buf, size_t nbytes, off_t offset)
171 {
172 int old_errno;
173 ssize_t ret;
174 
175  off_t old_offset = _tell(handle);
176 
177  if (0 > old_offset)
178  ret = (-1);
179  else
180  {
181  _lseek(handle, offset, SEEK_SET);
182  ret = _read(handle, buf, nbytes);
183 
184  old_errno = errno;
185  _lseek(handle, old_offset, SEEK_SET);
186  errno = old_errno;
187  }
188 
189  return (ret);
190 }
191 
192 
193 //***************************************************************
194 //
195 // pwrite()
196 //
197 // Emulates pwrite() using _lseek()/_write()/_lseek().
198 //
199 // Returns:
200 //
201 // On Success: The number of bytes written to the file
202 // On Failure: -1
203 //
205 pwrite(int handle, const void *buf, size_t nbytes, off_t offset)
206 {
207 int old_errno;
208 ssize_t ret;
209 
210  off_t old_offset = _lseek(handle, offset, SEEK_SET);
211 
212  if (0 > old_offset)
213  ret = (-1);
214  else
215  {
216  ret = _write(handle, buf, nbytes);
217 
218  old_errno = errno;
219  _lseek(handle, old_offset, SEEK_SET);
220  errno = old_errno;
221  }
222 
223  return (ret);
224 }
225 
226 //***************************************************************
227 //
228 // round()
229 //
230 // Emulates round() using floor().
231 //
232 // Returns:
233 //
234 // On Success: The largest integer that is less than or
235 // equal to 'x'.
236 // On Failure: None
237 //
239 round(double x)
240 {
241  return (floor(x));
242 }
243 
244 //***************************************************************
245 //
246 // trunc()
247 //
248 // Emulates trunc() using floor() and ceil().
249 //
250 // Returns:
251 //
252 // On Success: The largest integer whose magnitude is less
253 // than or equal to 'x' (regardless of sign).
254 // On Failure: None
255 //
257 trunc(double x)
258 {
259  if (x < 0)
260  return (ceil(x));
261 
262  return (floor(x));
263 }
264 
265 //***************************************************************
266 //
267 // log2()
268 //
269 // Emulates C99 log2() using log().
270 //
271 // Returns:
272 //
273 // On Success: The binary (base-2) logarithm of 'x'
274 // (e.g. log2(1024) == 10).
275 // On Failure: None, except that calling log(x) should generate
276 // an appropriate error for us (such as ERANGE etc).
277 //
279 log2(double x)
280 {
281  return (log(x) / log((double)2.0));
282 }
283 
284 namespace PBD {
285 
286 //***************************************************************
287 //
288 // TestForMinimumSpecOS()
289 //
290 // Tests the user's OS to see if it is Win2K or later (could be
291 // expanded quite easily to accommodate other OS's)
292 //
293 // Returns:
294 //
295 // On Success: TRUE (if the user's OS matches the minimum spec)
296 // On Failure: FALSE otherwise
297 //
299 TestForMinimumSpecOS(char *revision /* currently ignored */)
300 {
301 bool bRet = true;
302 #ifdef PLATFORM_WINDOWS
303  bRet = false;
304  HINSTANCE hKernelDll = (HINSTANCE)dlopen("kernel32.dll", RTLD_NOW);
305 
306  if (hKernelDll)
307  {
308  // 'CreateHardLink()' is only available from Win2K onwards.
309  if (NULL != dlsym(hKernelDll, "CreateHardLinkA"))
310  bRet = true;
311 
312  dlclose(hKernelDll);
313  }
314 #endif
315  // Other OS's could be accommodated here
316 
317  return (bRet);
318 }
319 
320 
321 //***************************************************************
322 //
323 // realpath()
324 //
325 // Emulates POSIX realpath() using Win32 _fullpath().
326 //
327 // Returns:
328 //
329 // On Success: A pointer to the resolved (absolute) path
330 // On Failure: NULL
331 //
333 realpath (const char *original_path, char resolved_path[_MAX_PATH+1])
334 {
335 char *pRet = NULL;
336 bool bIsSymLink = 0; // We'll probably need to test the incoming path
337  // to find out if it points to a Windows shortcut
338  // (or a hard link) and set this appropriately.
339  if (bIsSymLink)
340  {
341  // At the moment I'm not sure if Windows '_fullpath()' is directly
342  // equivalent to POSIX 'realpath()' - in as much as the latter will
343  // resolve the supplied path if it happens to point to a symbolic
344  // link ('_fullpath()' probably DOESN'T do this but I'm not really
345  // sure if Ardour needs such functionality anyway). Therefore we'll
346  // possibly need to add that functionality here at a later date.
347  }
348  else
349  {
350  char temp[(MAX_PATH+1)*6]; // Allow for maximum length of a path in UTF8 characters
351 
352  // POSIX 'realpath()' requires that the buffer size is at
353  // least PATH_MAX+1, so assume that the user knew this !!
354  pRet = _fullpath(temp, Glib::locale_from_utf8(original_path).c_str(), _MAX_PATH);
355  if (NULL != pRet)
356  strcpy(resolved_path, Glib::locale_to_utf8(temp).c_str());
357  }
358 
359  return (pRet);
360 }
361 
362 
363 //***************************************************************
364 //
365 // opendir()
366 //
367 // Creates a pointer to a DIR structure, appropriately filled in
368 // and ready to begin a directory search iteration.
369 //
370 // Returns:
371 //
372 // On Success: Pointer to a (heap based) DIR structure
373 // On Failure: NULL
374 //
376 opendir (const char *szPath)
377 {
378 wchar_t wpath[PATH_MAX+1];
379 unsigned int rc;
380 DIR *pDir = 0;
381 
382  errno = 0;
383 
384  if (!szPath)
385  errno = EFAULT;
386 
387  if ((!errno) && ('\0' == szPath[0]))
388  errno = ENOTDIR;
389 
390  // Determine if the given path really is a directory
391 
392  if (!errno)
393  if (0 == MultiByteToWideChar (CP_UTF8, 0, (LPCSTR)szPath, -1, (LPWSTR)wpath, sizeof(wpath)))
394  errno = EFAULT;
395 
396  if ((!errno) && ((rc = GetFileAttributesW(wpath)) == -1))
397  errno = ENOENT;
398 
399  if ((!errno) && (!(rc & FILE_ATTRIBUTE_DIRECTORY)))
400  // Error. Entry exists but not a directory. */
401  errno = ENOTDIR;
402 
403  if (!errno)
404  {
405  // Allocate enough memory to store DIR structure, plus
406  // the complete directory path originally supplied.
407  pDir = (DIR *)malloc(sizeof(DIR) + strlen(szPath) + strlen("\\") + strlen ("*"));
408 
409  if (!pDir)
410  {
411  // Error - out of memory
412  errno = ENOMEM;
413  }
414  }
415 
416  if (!errno)
417  {
418  // Create the search expression
419  strcpy(pDir->dd_name, szPath);
420 
421  // Add a backslash if the path doesn't already end with one
422  if (pDir->dd_name[0] != '\0' &&
423  pDir->dd_name[strlen(pDir->dd_name) - 1] != '/' &&
424  pDir->dd_name[strlen(pDir->dd_name) - 1] != '\\')
425  {
426  strcat (pDir->dd_name, "\\");
427  }
428 
429  // Add the search pattern
430  strcat(pDir->dd_name, "*");
431 
432  // Initialize handle to -1 so that a premature closedir()
433  // doesn't try to call _findclose() on it.
434  pDir->dd_handle = (-1);
435 
436  // Initialize the status
437  pDir->dd_stat = 0;
438 
439  // Initialize the dirent structure. 'ino' and 'reclen' are invalid under Win32
440  // and 'name' simply points at the appropriate part of the findfirst_t struct.
441  pDir->dd_dir.d_ino = 0;
442  pDir->dd_dir.d_reclen = 0;
443  pDir->dd_dir.d_namlen = 0;
444  strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name);
445 
446  return (pDir); // Succeeded
447  }
448 
449  if (pDir)
450  free (pDir);
451  return (DIR *) 0; // Failed
452 }
453 
454 
455 //***************************************************************
456 //
457 // readdir()
458 //
459 // Return a pointer to a dirent struct, filled with information
460 // about the next entry in the directory.
461 //
462 // Returns:
463 //
464 // On Success: A pointer to the supplied DIR's 'dirent' struct
465 // On Failure: NULL
466 //
467 LIBPBD_API struct dirent* PBD_APICALLTYPE
468 readdir (DIR* pDir)
469 {
470 int old_errno = 0;
471 errno = 0;
472 
473  // Check for valid DIR struct
474  if (!pDir)
475  errno = EFAULT;
476 
477  if ((strcmp(pDir->dd_dir.d_name, pDir->dd_dta.name)) && (!errno))
478  // The structure does not seem to be set up correctly
479  errno = EINVAL;
480  else
481  {
482  if (pDir->dd_stat < 0)
483  {
484  // We have already returned all files in this directory
485  // (or the structure has an invalid dd_stat).
486  return (struct dirent *)0;
487  }
488  else if (pDir->dd_stat == 0)
489  {
490  // We haven't started the search yet.
491  // Start the search
492  pDir->dd_handle = _findfirst (Glib::locale_from_utf8(pDir->dd_name).c_str(), &(pDir->dd_dta));
493 
494  if (pDir->dd_handle == -1)
495  // The directory is empty
496  pDir->dd_stat = -1;
497  else
498  pDir->dd_stat = 1;
499  }
500  else
501  {
502  // Do not return ENOENT on last file in directory
503  old_errno = errno;
504 
505  // Get the next search entry
506  if (_findnext (pDir->dd_handle, &(pDir->dd_dta)))
507  {
508  // We are off the end or otherwise error
509  errno = old_errno;
510  _findclose (pDir->dd_handle);
511  pDir->dd_handle = -1;
512  pDir->dd_stat = -1;
513  }
514  else
515  // Update to indicate the correct status number
516  pDir->dd_stat++;
517  }
518 
519  if (pDir->dd_stat > 0)
520  {
521  // We successfully got an entry. Details about the file are
522  // already appropriately filled in except for the length of
523  // file name.
524  strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name);
525  pDir->dd_dir.d_namlen = strlen (pDir->dd_dir.d_name);
526  return (&pDir->dd_dir); // Succeeded
527  }
528  }
529 
530  return (struct dirent *) 0; // Failed
531 }
532 
533 
534 //***************************************************************
535 //
536 // closedir()
537 //
538 // Frees the resources allocated by opendir().
539 //
540 // Returns:
541 //
542 // On Success: 0
543 // On Failure: -1
544 //
546 closedir (DIR *pDir)
547 {
548 int rc = 0;
549 
550  errno = 0;
551 
552  if (!pDir)
553  errno = EFAULT;
554  else
555  {
556  if ((-1) != pDir->dd_handle)
557  rc = _findclose (pDir->dd_handle);
558 
559  // Free the DIR structure
560  free (pDir);
561 
562  return rc; // Succeeded
563  }
564 
565  return (-1); // Failed
566 }
567 
568 //***************************************************************
569 //
570 // mkstemp()
571 //
572 // Emulates Linux mkstemp() using Win32 _mktemp() and _open() etc.
573 //
574 // Returns:
575 //
576 // On Success: A file descriptor for the opened file.
577 // On Failure: (-1)
578 //
580 mkstemp (char *template_name)
581 {
582 int ret = (-1);
583 char *szFileName;
584 char szTempPath[PATH_MAX+100]; // Just ensure we have plenty of buffer space
585 
586  if (NULL != (szFileName = _mktemp(template_name)))
587  {
588  if (0 != ::GetTempPathA(sizeof(szTempPath), szTempPath))
589  {
590  strcat(szTempPath, szFileName);
591  ret = _open(szTempPath, (_O_CREAT|_O_BINARY|_O_TEMPORARY|_O_RDWR|_O_TRUNC), _S_IWRITE);
592  }
593  }
594 
595  return (ret);
596 }
597 
598 
599 //***************************************************************
600 //
601 // ntfs_link()
602 //
603 // Emulates Linux link() using Win32 CreateHardLink()(NTFS only).
604 //
605 // Returns:
606 //
607 // On Success: Non-zero.
608 // On Failure: Zero (call 'GetLastError()' to retrieve info)
609 //
611 ntfs_link (const char *existing_filepath, const char *link_filepath)
612 {
613 int ret = 1; // 'ERROR_INVALID_FUNCTION'
614 bool bValidPath = false;
615 
616  // Make sure we've been sent a valid input string
617  if (existing_filepath && link_filepath)
618  {
619  std::string strRoot = existing_filepath;
620 
621  if ((1 < strRoot.length()) && ('\\' == existing_filepath[0]) && ('\\' == existing_filepath[1]))
622  {
623  int slashcnt = 0;
624 
625  // We've been sent a network path. Convert backslashes to forward slashes temporarily.
626  std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
627 
628  // Now, if there are less than four slashes, add a fourth one or abort
629  std::string::iterator iter = strRoot.begin();
630  while ((slashcnt < 4) && (iter != strRoot.end()))
631  {
632  if ('/' == (*iter))
633  slashcnt++;
634 
635  ++iter;
636  }
637 
638  if (slashcnt > 2)
639  {
640  // If only 3 slashes were counted, add a trailing slash
641  if (slashcnt == 3)
642  strRoot += '/';
643 
644  // Now find the position of the fourth slash
645  iter = strRoot.begin();
646  int charcnt = 0;
647  for (slashcnt=0; slashcnt<4;)
648  {
649  charcnt++;
650 
651  if ('/' == (*iter))
652  slashcnt++;
653 
654  if (++iter == strRoot.end())
655  break;
656  }
657 
658  strRoot.resize(charcnt);
659  bValidPath = true;
660  }
661  }
662  else
663  {
664  // Assume a standard Windows style path
665  if (1 < strRoot.length() && (':' == existing_filepath[1]))
666  {
667  // Convert backslashes to forward slashes temporarily.
668  std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
669 
670  if (2 == strRoot.length())
671  strRoot += '/';
672 
673  if ('/' == strRoot[2])
674  {
675  strRoot.resize(3);
676  bValidPath = true;
677  }
678  }
679  }
680 
681  if (bValidPath)
682  {
683  char szFileSystemType[_MAX_PATH+1];
684 
685  // Restore the original backslashes
686  std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash);
687 
688  // Windows only supports hard links for the NTFS filing
689  // system, so let's make sure that's what we're using!!
690  if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1))
691  {
692  std::string strRootFileSystemType = szFileSystemType;
693  std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper);
694 #if (_WIN32_WINNT >= 0x0500)
695  if (0 == strRootFileSystemType.compare("NTFS"))
696  {
697  if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards
698  if (0 == CreateHardLinkA(link_filepath, existing_filepath, NULL))
699  { // Note that the above API call cannot create a link to a directory, so
700  // should we also be checking that the supplied path was actually a file?
701  ret = GetLastError();
702  }
703  else
704  SetLastError(ret = 0); // 'NO_ERROR'
705  }
706  else
707  {
708  ret = 4300; // 'ERROR_INVALID_MEDIA'
709  }
710 #endif
711  }
712  }
713  else
714  ret = 123; // 'ERROR_INVALID_NAME'
715  }
716  else
717  ret = 161; // 'ERROR_BAD_PATHNAME'
718 
719  if (ret)
720  {
721  SetLastError(ret);
722  return (-1);
723  }
724  else
725  return (0);
726 }
727 
728 
729 //***************************************************************
730 //
731 // ntfs_unlink()
732 //
733 // Emulates Linux unlink() using Win32 DeleteFile()(NTFS only).
734 //
735 // Returns:
736 //
737 // On Success: Non-zero.
738 // On Failure: Zero (call 'GetLastError()' to retrieve info)
739 //
741 ntfs_unlink (const char *link_filepath)
742 {
743 int ret = 1; // 'ERROR_INVALID_FUNCTION'
744 bool bValidPath = false;
745 
746  // Make sure we've been sent a valid input string
747  if (link_filepath)
748  {
749  std::string strRoot = link_filepath;
750 
751  if ((1 < strRoot.length()) && ('\\' == link_filepath[0]) && ('\\' == link_filepath[1]))
752  {
753  int slashcnt = 0;
754 
755  // We've been sent a network path. Convert backslashes to forward slashes temporarily.
756  std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
757 
758  // Now, if there are less than four slashes, add a fourth one or abort
759  std::string::iterator iter = strRoot.begin();
760  while ((slashcnt < 4) && (iter != strRoot.end()))
761  {
762  if ('/' == (*iter))
763  slashcnt++;
764 
765  ++iter;
766  }
767 
768  if (slashcnt > 2)
769  {
770  // If only 3 slashes were counted, add a trailing slash
771  if (slashcnt == 3)
772  strRoot += '/';
773 
774  // Now find the position of the fourth slash
775  iter = strRoot.begin();
776  int charcnt = 0;
777  for (slashcnt=0; slashcnt<4;)
778  {
779  charcnt++;
780 
781  if ('/' == (*iter))
782  slashcnt++;
783 
784  if (++iter == strRoot.end())
785  break;
786  }
787 
788  strRoot.resize(charcnt);
789  bValidPath = true;
790  }
791  }
792  else
793  {
794  // Assume a standard Windows style path
795  if (1 < strRoot.length() && (':' == link_filepath[1]))
796  {
797  // Convert backslashes to forward slashes temporarily.
798  std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
799 
800  if (2 == strRoot.length())
801  strRoot += '/';
802 
803  if ('/' == strRoot[2])
804  {
805  strRoot.resize(3);
806  bValidPath = true;
807  }
808  }
809  }
810 
811  if (bValidPath)
812  {
813  char szFileSystemType[_MAX_PATH+1];
814 
815  // Restore the original backslashes
816  std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash);
817 
818  // Windows only supports hard links for the NTFS filing
819  // system, so let's make sure that's what we're using!!
820  if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1))
821  {
822  std::string strRootFileSystemType = szFileSystemType;
823  std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper);
824 #if (_WIN32_WINNT >= 0x0500)
825  if (0 == strRootFileSystemType.compare("NTFS"))
826  if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards
827  if (0 == DeleteFileA(link_filepath))
828  ret = GetLastError();
829  else
830  ret = 0; // 'NO_ERROR'
831 #endif
832  }
833  }
834  else
835  ret = 123; // 'ERROR_INVALID_NAME'
836  }
837  else
838  ret = 161; // 'ERROR_BAD_PATHNAME'
839 
840  if (ret)
841  {
842  SetLastError(ret);
843  return (-1);
844  }
845  else
846  return (0);
847 }
848 
849 } // namespace PBD
850 
851 
852 //***************************************************************
853 //
854 // dlopen()
855 //
856 // Emulates POSIX dlopen() using Win32 LoadLibrary().
857 //
858 // Returns:
859 //
860 // On Success: A handle to the opened DLL
861 // On Failure: NULL
862 //
864 dlopen (const char *file_name, int mode)
865 {
866  // Note that 'mode' is ignored in Win32
867  return(::LoadLibraryA(Glib::locale_from_utf8(file_name).c_str()));
868 }
869 
870 
871 //***************************************************************
872 //
873 // dlclose()
874 //
875 // Emulates POSIX dlclose() using Win32 FreeLibrary().
876 //
877 // Returns:
878 //
879 // On Success: A non-zero number
880 // On Failure: 0
881 //
883 dlclose (void *handle)
884 {
885  return (::FreeLibrary((HMODULE)handle));
886 }
887 
888 
889 //***************************************************************
890 //
891 // dlsym()
892 //
893 // Emulates POSIX dlsym() using Win32 GetProcAddress().
894 //
895 // Returns:
896 //
897 // On Success: A pointer to the found function or symbol
898 // On Failure: NULL
899 //
901 dlsym (void *handle, const char *symbol_name)
902 {
903  // First test for RTLD_DEFAULT and RTLD_NEXT
904  if ((handle == 0/*RTLD_DEFAULT*/) || (handle == ((void *) -1L)/*RTLD_NEXT*/))
905  {
906  return 0; // Not yet supported for Win32
907  }
908  else
909  return (::GetProcAddress((HMODULE)handle, symbol_name));
910 }
911 
912 #define LOCAL_ERROR_BUF_SIZE 1024
913 static char szLastWinError[LOCAL_ERROR_BUF_SIZE];
914 //***************************************************************
915 //
916 // dlerror()
917 //
918 // Emulates POSIX dlerror() using Win32 GetLastError().
919 //
920 // Returns:
921 //
922 // On Success: The translated message corresponding to the
923 // last error
924 // On Failure: NULL (if the last error was ERROR_SUCCESS)
925 //
927 dlerror ()
928 {
929  DWORD dwLastErrorId = GetLastError();
930  if (ERROR_SUCCESS == dwLastErrorId)
931  return 0;
932  else
933  {
934  if (0 == FormatMessage(
935  FORMAT_MESSAGE_FROM_SYSTEM,
936  NULL,
937  dwLastErrorId,
938  0,
939  szLastWinError,
940  LOCAL_ERROR_BUF_SIZE,
941  0))
942  {
943  sprintf(szLastWinError, "Could not decipher the previous error message");
944  }
945 
946  // POSIX dlerror() seems to reset the
947  // error system, so emulate that here
948  SetLastError(ERROR_SUCCESS);
949  }
950 
951  return(szLastWinError);
952 }
953 
954 #endif // COMPILER_MSVC
bool operator<(shared_ptr< T > const &a, shared_ptr< U > const &b)
Definition: shared_ptr.hpp:376
bool operator!=(shared_ptr< T > const &a, shared_ptr< U > const &b)
Definition: shared_ptr.hpp:360
#define LIBPBD_API
LIBARDOUR_API const char * revision
Definition: revision.cc:2
#define PATH_MAX
Definition: lv2_plugin.h:34
#define _MAX_PATH
bool operator==(const RouteProcessorSelection &a, const RouteProcessorSelection &b)
Definition: debug.h:30
#define PBD_APICALLTYPE
Definition: msvc_pbd.h:55