NAP
direntw32.h
1 /*
2  * Dirent interface for Microsoft Visual Studio
3  * Version 1.21
4  *
5  * Copyright (C) 2006-2012 Toni Ronkko
6  * This file is part of dirent. Dirent may be freely distributed
7  * under the MIT license. For all details and documentation, see
8  * https://github.com/tronkko/dirent
9  */
10 #ifndef DIRENT_H
11 #define DIRENT_H
12 
13 /*
14  * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
15  * Windows Sockets 2.0.
16  */
17 #ifndef WIN32_LEAN_AND_MEAN
18 # define WIN32_LEAN_AND_MEAN
19 #endif
20 #include <windows.h>
21 
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <wchar.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <malloc.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 
32 /* Indicates that d_type field is available in dirent structure */
33 #define _DIRENT_HAVE_D_TYPE
34 
35 /* Indicates that d_namlen field is available in dirent structure */
36 #define _DIRENT_HAVE_D_NAMLEN
37 
38 /* Entries missing from MSVC 6.0 */
39 #if !defined(FILE_ATTRIBUTE_DEVICE)
40 # define FILE_ATTRIBUTE_DEVICE 0x40
41 #endif
42 
43 /* File type and permission getFlags for stat(), general mask */
44 #if !defined(S_IFMT)
45 # define S_IFMT _S_IFMT
46 #endif
47 
48 /* Directory bit */
49 #if !defined(S_IFDIR)
50 # define S_IFDIR _S_IFDIR
51 #endif
52 
53 /* Character device bit */
54 #if !defined(S_IFCHR)
55 # define S_IFCHR _S_IFCHR
56 #endif
57 
58 /* Pipe bit */
59 #if !defined(S_IFFIFO)
60 # define S_IFFIFO _S_IFFIFO
61 #endif
62 
63 /* Regular file bit */
64 #if !defined(S_IFREG)
65 # define S_IFREG _S_IFREG
66 #endif
67 
68 /* Read permission */
69 #if !defined(S_IREAD)
70 # define S_IREAD _S_IREAD
71 #endif
72 
73 /* Write permission */
74 #if !defined(S_IWRITE)
75 # define S_IWRITE _S_IWRITE
76 #endif
77 
78 /* Execute permission */
79 #if !defined(S_IEXEC)
80 # define S_IEXEC _S_IEXEC
81 #endif
82 
83 /* Pipe */
84 #if !defined(S_IFIFO)
85 # define S_IFIFO _S_IFIFO
86 #endif
87 
88 /* Block device */
89 #if !defined(S_IFBLK)
90 # define S_IFBLK 0
91 #endif
92 
93 /* Link */
94 #if !defined(S_IFLNK)
95 # define S_IFLNK 0
96 #endif
97 
98 /* Socket */
99 #if !defined(S_IFSOCK)
100 # define S_IFSOCK 0
101 #endif
102 
103 /* Read user permission */
104 #if !defined(S_IRUSR)
105 # define S_IRUSR S_IREAD
106 #endif
107 
108 /* Write user permission */
109 #if !defined(S_IWUSR)
110 # define S_IWUSR S_IWRITE
111 #endif
112 
113 /* Execute user permission */
114 #if !defined(S_IXUSR)
115 # define S_IXUSR 0
116 #endif
117 
118 /* Read group permission */
119 #if !defined(S_IRGRP)
120 # define S_IRGRP 0
121 #endif
122 
123 /* Write group permission */
124 #if !defined(S_IWGRP)
125 # define S_IWGRP 0
126 #endif
127 
128 /* Execute group permission */
129 #if !defined(S_IXGRP)
130 # define S_IXGRP 0
131 #endif
132 
133 /* Read others permission */
134 #if !defined(S_IROTH)
135 # define S_IROTH 0
136 #endif
137 
138 /* Write others permission */
139 #if !defined(S_IWOTH)
140 # define S_IWOTH 0
141 #endif
142 
143 /* Execute others permission */
144 #if !defined(S_IXOTH)
145 # define S_IXOTH 0
146 #endif
147 
148 /* Maximum length of file name */
149 #if !defined(PATH_MAX)
150 # define PATH_MAX MAX_PATH
151 #endif
152 #if !defined(FILENAME_MAX)
153 # define FILENAME_MAX MAX_PATH
154 #endif
155 #if !defined(NAME_MAX)
156 # define NAME_MAX FILENAME_MAX
157 #endif
158 
159 /* File type getFlags for d_type */
160 #define DT_UNKNOWN 0
161 #define DT_REG S_IFREG
162 #define DT_DIR S_IFDIR
163 #define DT_FIFO S_IFIFO
164 #define DT_SOCK S_IFSOCK
165 #define DT_CHR S_IFCHR
166 #define DT_BLK S_IFBLK
167 #define DT_LNK S_IFLNK
168 
169 /* Macros for converting between st_mode and d_type */
170 #define IFTODT(mode) ((mode) & S_IFMT)
171 #define DTTOIF(type) (type)
172 
173 /*
174  * File type macros. Note that block devices, sockets and links cannot be
175  * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
176  * only defined for compatibility. These macros should always return false
177  * on Windows.
178  */
179 #if !defined(S_ISFIFO)
180 # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
181 #endif
182 #if !defined(S_ISDIR)
183 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
184 #endif
185 #if !defined(S_ISREG)
186 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
187 #endif
188 #if !defined(S_ISLNK)
189 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
190 #endif
191 #if !defined(S_ISSOCK)
192 # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
193 #endif
194 #if !defined(S_ISCHR)
195 # define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
196 #endif
197 #if !defined(S_ISBLK)
198 # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
199 #endif
200 
201 /* Return the exact length of d_namlen without zero terminator */
202 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
203 
204 /* Return number of bytes needed to store d_namlen */
205 #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
206 
207 
208 #ifdef __cplusplus
209 extern "C" {
210 #endif
211 
212 
213 /* Wide-character version */
214 struct _wdirent {
215  /* Always zero */
216  long d_ino;
217 
218  /* Structure size */
219  unsigned short d_reclen;
220 
221  /* Length of name without \0 */
222  size_t d_namlen;
223 
224  /* File type */
225  int d_type;
226 
227  /* File name */
228  wchar_t d_name[PATH_MAX];
229 };
230 typedef struct _wdirent _wdirent;
231 
232 struct _WDIR {
233  /* Current directory entry */
234  struct _wdirent ent;
235 
236  /* Private file data */
237  WIN32_FIND_DATAW data;
238 
239  /* True if data is valid */
240  int cached;
241 
242  /* Win32 search handle */
243  HANDLE handle;
244 
245  /* Initial directory name */
246  wchar_t *patt;
247 };
248 typedef struct _WDIR _WDIR;
249 
250 static _WDIR *_wopendir (const wchar_t *dirname);
251 static struct _wdirent *_wreaddir (_WDIR *dirp);
252 static int _wclosedir (_WDIR *dirp);
253 static void _wrewinddir (_WDIR* dirp);
254 
255 
256 /* For compatibility with Symbian */
257 #define wdirent _wdirent
258 #define WDIR _WDIR
259 #define wopendir _wopendir
260 #define wreaddir _wreaddir
261 #define wclosedir _wclosedir
262 #define wrewinddir _wrewinddir
263 
264 
265 /* Multi-byte character versions */
266 struct dirent {
267  /* Always zero */
268  long d_ino;
269 
270  /* Structure size */
271  unsigned short d_reclen;
272 
273  /* Length of name without \0 */
274  size_t d_namlen;
275 
276  /* File type */
277  int d_type;
278 
279  /* File name */
280  char d_name[PATH_MAX];
281 };
282 typedef struct dirent dirent;
283 
284 struct DIR {
285  struct dirent ent;
286  struct _WDIR *wdirp;
287 };
288 typedef struct DIR DIR;
289 
290 static DIR *opendir (const char *dirname);
291 static struct dirent *readdir (DIR *dirp);
292 static int closedir (DIR *dirp);
293 static void rewinddir (DIR* dirp);
294 
295 
296 /* Internal utility functions */
297 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
298 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
299 
300 static int dirent_mbstowcs_s(
301  size_t *pReturnValue,
302  wchar_t *wcstr,
303  size_t sizeInWords,
304  const char *mbstr,
305  size_t count);
306 
307 static int dirent_wcstombs_s(
308  size_t *pReturnValue,
309  char *mbstr,
310  size_t sizeInBytes,
311  const wchar_t *wcstr,
312  size_t count);
313 
314 static void dirent_set_errno (int error);
315 
316 /*
317  * Open directory stream DIRNAME for read and return a pointer to the
318  * internal working area that is used to retrieve individual directory
319  * entries.
320  */
321 static _WDIR*
322 _wopendir(
323  const wchar_t *dirname)
324 {
325  _WDIR *dirp = NULL;
326  int error;
327 
328  /* Must have directory name */
329  if (dirname == NULL || dirname[0] == '\0') {
330  dirent_set_errno (ENOENT);
331  return NULL;
332  }
333 
334  /* Allocate new _WDIR structure */
335  dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
336  if (dirp != NULL) {
337  DWORD n;
338 
339  /* Reset _WDIR structure */
340  dirp->handle = INVALID_HANDLE_VALUE;
341  dirp->patt = NULL;
342  dirp->cached = 0;
343 
344  /* Compute the length of full path plus zero terminator
345  *
346  * Note that on WinRT there's no way to convert relative paths
347  * into absolute paths, so just assume its an absolute path.
348  */
349 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
350  n = wcslen(dirname);
351 # else
352  n = GetFullPathNameW (dirname, 0, NULL, NULL);
353 # endif
354 
355  /* Allocate room for absolute directory name and search pattern */
356  dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
357  if (dirp->patt) {
358 
359  /*
360  * Convert relative directory name to an absolute one. This
361  * allows rewinddir() to function correctly even when current
362  * working directory is changed between opendir() and rewinddir().
363  *
364  * Note that on WinRT there's no way to convert relative paths
365  * into absolute paths, so just assume its an absolute path.
366  */
367 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
368  wcsncpy_s(dirp->patt, n+1, dirname, n);
369 # else
370  n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
371 # endif
372  if (n > 0) {
373  wchar_t *p;
374 
375  /* Append search pattern \* to the directory name */
376  p = dirp->patt + n;
377  if (dirp->patt < p) {
378  switch (p[-1]) {
379  case '\\':
380  case '/':
381  case ':':
382  /* Directory ends in path separator, e.g. c:\temp\ */
383  /*NOP*/;
384  break;
385 
386  default:
387  /* Directory name doesn't end in path separator */
388  *p++ = '\\';
389  }
390  }
391  *p++ = '*';
392  *p = '\0';
393 
394  /* Open directory stream and retrieve the first entry */
395  if (dirent_first (dirp)) {
396  /* Directory stream opened successfully */
397  error = 0;
398  } else {
399  /* Cannot retrieve first entry */
400  error = 1;
401  dirent_set_errno (ENOENT);
402  }
403 
404  } else {
405  /* Cannot retrieve full path name */
406  dirent_set_errno (ENOENT);
407  error = 1;
408  }
409 
410  } else {
411  /* Cannot allocate memory for search pattern */
412  error = 1;
413  }
414 
415  } else {
416  /* Cannot allocate _WDIR structure */
417  error = 1;
418  }
419 
420  /* Clean up in case of error */
421  if (error && dirp) {
422  _wclosedir (dirp);
423  dirp = NULL;
424  }
425 
426  return dirp;
427 }
428 
429 /*
430  * Read next directory entry. The directory entry is returned in dirent
431  * structure in the d_name field. Individual directory entries returned by
432  * this function include regular files, sub-directories, pseudo-directories
433  * "." and ".." as well as volume labels, hidden files and system files.
434  */
435 static struct _wdirent*
436 _wreaddir(
437  _WDIR *dirp)
438 {
439  WIN32_FIND_DATAW *datap;
440  struct _wdirent *entp;
441 
442  /* Read next directory entry */
443  datap = dirent_next (dirp);
444  if (datap) {
445  size_t n;
446  DWORD attr;
447 
448  /* Pointer to directory entry to return */
449  entp = &dirp->ent;
450 
451  /*
452  * Copy file name as wide-character string. If the file name is too
453  * long to fit in to the destination buffer, then truncate file name
454  * to PATH_MAX characters and zero-terminate the buffer.
455  */
456  n = 0;
457  while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
458  entp->d_name[n] = datap->cFileName[n];
459  n++;
460  }
461  dirp->ent.d_name[n] = 0;
462 
463  /* Length of file name excluding zero terminator */
464  entp->d_namlen = n;
465 
466  /* File type */
467  attr = datap->dwFileAttributes;
468  if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
469  entp->d_type = DT_CHR;
470  } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
471  entp->d_type = DT_DIR;
472  } else {
473  entp->d_type = DT_REG;
474  }
475 
476  /* Reset dummy fields */
477  entp->d_ino = 0;
478  entp->d_reclen = sizeof (struct _wdirent);
479 
480  } else {
481 
482  /* Last directory entry read */
483  entp = NULL;
484 
485  }
486 
487  return entp;
488 }
489 
490 /*
491  * Close directory stream opened by opendir() function. This invalidates the
492  * DIR structure as well as any directory entry read previously by
493  * _wreaddir().
494  */
495 static int
496 _wclosedir(
497  _WDIR *dirp)
498 {
499  int ok;
500  if (dirp) {
501 
502  /* Release search handle */
503  if (dirp->handle != INVALID_HANDLE_VALUE) {
504  FindClose (dirp->handle);
505  dirp->handle = INVALID_HANDLE_VALUE;
506  }
507 
508  /* Release search pattern */
509  if (dirp->patt) {
510  free (dirp->patt);
511  dirp->patt = NULL;
512  }
513 
514  /* Release directory structure */
515  free (dirp);
516  ok = /*success*/0;
517 
518  } else {
519  /* Invalid directory stream */
520  dirent_set_errno (EBADF);
521  ok = /*failure*/-1;
522  }
523  return ok;
524 }
525 
526 /*
527  * Rewind directory stream such that _wreaddir() returns the very first
528  * file name again.
529  */
530 static void
531 _wrewinddir(
532  _WDIR* dirp)
533 {
534  if (dirp) {
535  /* Release existing search handle */
536  if (dirp->handle != INVALID_HANDLE_VALUE) {
537  FindClose (dirp->handle);
538  }
539 
540  /* Open new search handle */
541  dirent_first (dirp);
542  }
543 }
544 
545 /* Get first directory entry (internal) */
546 static WIN32_FIND_DATAW*
547 dirent_first(
548  _WDIR *dirp)
549 {
550  WIN32_FIND_DATAW *datap;
551 
552  /* Open directory and retrieve the first entry */
553  dirp->handle = FindFirstFileExW(
554  dirp->patt, FindExInfoStandard, &dirp->data,
555  FindExSearchNameMatch, NULL, 0);
556  if (dirp->handle != INVALID_HANDLE_VALUE) {
557 
558  /* a directory entry is now waiting in memory */
559  datap = &dirp->data;
560  dirp->cached = 1;
561 
562  } else {
563 
564  /* Failed to re-open directory: no directory entry in memory */
565  dirp->cached = 0;
566  datap = NULL;
567 
568  }
569  return datap;
570 }
571 
572 /* Get next directory entry (internal) */
573 static WIN32_FIND_DATAW*
574 dirent_next(
575  _WDIR *dirp)
576 {
577  WIN32_FIND_DATAW *p;
578 
579  /* Get next directory entry */
580  if (dirp->cached != 0) {
581 
582  /* A valid directory entry already in memory */
583  p = &dirp->data;
584  dirp->cached = 0;
585 
586  } else if (dirp->handle != INVALID_HANDLE_VALUE) {
587 
588  /* Get the next directory entry from stream */
589  if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
590  /* Got a file */
591  p = &dirp->data;
592  } else {
593  /* The very last entry has been processed or an error occured */
594  FindClose (dirp->handle);
595  dirp->handle = INVALID_HANDLE_VALUE;
596  p = NULL;
597  }
598 
599  } else {
600 
601  /* End of directory stream reached */
602  p = NULL;
603 
604  }
605 
606  return p;
607 }
608 
609 /*
610  * Open directory stream using plain old C-string.
611  */
612 static DIR*
613 opendir(
614  const char *dirname)
615 {
616  struct DIR *dirp;
617  int error;
618 
619  /* Must have directory name */
620  if (dirname == NULL || dirname[0] == '\0') {
621  dirent_set_errno (ENOENT);
622  return NULL;
623  }
624 
625  /* Allocate memory for DIR structure */
626  dirp = (DIR*) malloc (sizeof (struct DIR));
627  if (dirp) {
628  wchar_t wname[PATH_MAX];
629  size_t n;
630 
631  /* Convert directory name to wide-character string */
632  error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
633  if (!error) {
634 
635  /* Open directory stream using wide-character name */
636  dirp->wdirp = _wopendir (wname);
637  if (dirp->wdirp) {
638  /* Directory stream opened */
639  error = 0;
640  } else {
641  /* Failed to open directory stream */
642  error = 1;
643  }
644 
645  } else {
646  /*
647  * Cannot convert file name to wide-character string. This
648  * occurs if the string contains invalid multi-byte sequences or
649  * the output buffer is too small to contain the resulting
650  * string.
651  */
652  error = 1;
653  }
654 
655  } else {
656  /* Cannot allocate DIR structure */
657  error = 1;
658  }
659 
660  /* Clean up in case of error */
661  if (error && dirp) {
662  free (dirp);
663  dirp = NULL;
664  }
665 
666  return dirp;
667 }
668 
669 /*
670  * Read next directory entry.
671  *
672  * When working with text consoles, please note that file names returned by
673  * readdir() are represented in the default ANSI code page while any output to
674  * console is typically formatted on another code page. Thus, non-ASCII
675  * characters in file names will not usually display correctly on console. The
676  * problem can be fixed in two ways: (1) change the character set of console
677  * to 1252 using chcp utility and use Lucida Console font, or (2) use
678  * _cprintf function when writing to console. The _cprinf() will re-encode
679  * ANSI strings to the console code page so many non-ASCII characters will
680  * display correcly.
681  */
682 static struct dirent*
683 readdir(
684  DIR *dirp)
685 {
686  WIN32_FIND_DATAW *datap;
687  struct dirent *entp;
688 
689  /* Read next directory entry */
690  datap = dirent_next (dirp->wdirp);
691  if (datap) {
692  size_t n;
693  int error;
694 
695  /* Attempt to convert file name to multi-byte string */
696  error = dirent_wcstombs_s(
697  &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
698 
699  /*
700  * If the file name cannot be represented by a multi-byte string,
701  * then attempt to use old 8+3 file name. This allows traditional
702  * Unix-code to access some file names despite of unicode
703  * characters, although file names may seem unfamiliar to the user.
704  *
705  * Be ware that the code below cannot come up with a short file
706  * name unless the file system provides one. At least
707  * VirtualBox shared folders fail to do this.
708  */
709  if (error && datap->cAlternateFileName[0] != '\0') {
710  error = dirent_wcstombs_s(
711  &n, dirp->ent.d_name, PATH_MAX,
712  datap->cAlternateFileName, PATH_MAX);
713  }
714 
715  if (!error) {
716  DWORD attr;
717 
718  /* Initialize directory entry for return */
719  entp = &dirp->ent;
720 
721  /* Length of file name excluding zero terminator */
722  entp->d_namlen = n - 1;
723 
724  /* File attributes */
725  attr = datap->dwFileAttributes;
726  if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
727  entp->d_type = DT_CHR;
728  } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
729  entp->d_type = DT_DIR;
730  } else {
731  entp->d_type = DT_REG;
732  }
733 
734  /* Reset dummy fields */
735  entp->d_ino = 0;
736  entp->d_reclen = sizeof (struct dirent);
737 
738  } else {
739  /*
740  * Cannot convert file name to multi-byte string so construct
741  * an errornous directory entry and return that. Note that
742  * we cannot return NULL as that would stop the processing
743  * of directory entries completely.
744  */
745  entp = &dirp->ent;
746  entp->d_name[0] = '?';
747  entp->d_name[1] = '\0';
748  entp->d_namlen = 1;
749  entp->d_type = DT_UNKNOWN;
750  entp->d_ino = 0;
751  entp->d_reclen = 0;
752  }
753 
754  } else {
755  /* No more directory entries */
756  entp = NULL;
757  }
758 
759  return entp;
760 }
761 
762 /*
763  * Close directory stream.
764  */
765 static int
766 closedir(
767  DIR *dirp)
768 {
769  int ok;
770  if (dirp) {
771 
772  /* Close wide-character directory stream */
773  ok = _wclosedir (dirp->wdirp);
774  dirp->wdirp = NULL;
775 
776  /* Release multi-byte character version */
777  free (dirp);
778 
779  } else {
780 
781  /* Invalid directory stream */
782  dirent_set_errno (EBADF);
783  ok = /*failure*/-1;
784 
785  }
786  return ok;
787 }
788 
789 /*
790  * Rewind directory stream to beginning.
791  */
792 static void
793 rewinddir(
794  DIR* dirp)
795 {
796  /* Rewind wide-character string directory stream */
797  _wrewinddir (dirp->wdirp);
798 }
799 
800 /* Convert multi-byte string to wide character string */
801 static int
802 dirent_mbstowcs_s(
803  size_t *pReturnValue,
804  wchar_t *wcstr,
805  size_t sizeInWords,
806  const char *mbstr,
807  size_t count)
808 {
809  int error;
810 
811 #if defined(_MSC_VER) && _MSC_VER >= 1400
812 
813  /* Microsoft Visual Studio 2005 or later */
814  error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
815 
816 #else
817 
818  /* Older Visual Studio or non-Microsoft compiler */
819  size_t n;
820 
821  /* Convert to wide-character string (or count characters) */
822  n = mbstowcs (wcstr, mbstr, sizeInWords);
823  if (!wcstr || n < count) {
824 
825  /* Zero-terminate output buffer */
826  if (wcstr && sizeInWords) {
827  if (n >= sizeInWords) {
828  n = sizeInWords - 1;
829  }
830  wcstr[n] = 0;
831  }
832 
833  /* Length of resuting multi-byte string WITH zero terminator */
834  if (pReturnValue) {
835  *pReturnValue = n + 1;
836  }
837 
838  /* Success */
839  error = 0;
840 
841  } else {
842 
843  /* Could not convert string */
844  error = 1;
845 
846  }
847 
848 #endif
849 
850  return error;
851 }
852 
853 /* Convert wide-character string to multi-byte string */
854 static int
855 dirent_wcstombs_s(
856  size_t *pReturnValue,
857  char *mbstr,
858  size_t sizeInBytes, /* max size of mbstr */
859  const wchar_t *wcstr,
860  size_t count)
861 {
862  int error;
863 
864 #if defined(_MSC_VER) && _MSC_VER >= 1400
865 
866  /* Microsoft Visual Studio 2005 or later */
867  error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
868 
869 #else
870 
871  /* Older Visual Studio or non-Microsoft compiler */
872  size_t n;
873 
874  /* Convert to multi-byte string (or count the number of bytes needed) */
875  n = wcstombs (mbstr, wcstr, sizeInBytes);
876  if (!mbstr || n < count) {
877 
878  /* Zero-terminate output buffer */
879  if (mbstr && sizeInBytes) {
880  if (n >= sizeInBytes) {
881  n = sizeInBytes - 1;
882  }
883  mbstr[n] = '\0';
884  }
885 
886  /* Length of resulting multi-bytes string WITH zero-terminator */
887  if (pReturnValue) {
888  *pReturnValue = n + 1;
889  }
890 
891  /* Success */
892  error = 0;
893 
894  } else {
895 
896  /* Cannot convert string */
897  error = 1;
898 
899  }
900 
901 #endif
902 
903  return error;
904 }
905 
906 /* Set errno variable */
907 static void
908 dirent_set_errno(
909  int error)
910 {
911 #if defined(_MSC_VER) && _MSC_VER >= 1400
912 
913  /* Microsoft Visual Studio 2005 and later */
914  _set_errno (error);
915 
916 #else
917 
918  /* Non-Microsoft compiler or older Microsoft compiler */
919  errno = error;
920 
921 #endif
922 }
923 
924 
925 #ifdef __cplusplus
926 }
927 #endif
928 #endif /*DIRENT_H*/
929 
nap::icon::error
constexpr const char * error
Definition: imguiservice.h:55
nap::icon::ok
constexpr const char * ok
Definition: imguiservice.h:45