misc/libphysfs/platform_windows.c
changeset 12213 bb5522e88ab2
parent 10017 de822cd3df3a
child 13870 a966b1914792
equal deleted inserted replaced
12212:ea891871f481 12213:bb5522e88ab2
     8 
     8 
     9 #define __PHYSICSFS_INTERNAL__
     9 #define __PHYSICSFS_INTERNAL__
    10 #include "physfs_platforms.h"
    10 #include "physfs_platforms.h"
    11 
    11 
    12 #ifdef PHYSFS_PLATFORM_WINDOWS
    12 #ifdef PHYSFS_PLATFORM_WINDOWS
       
    13 #ifndef PHYSFS_PLATFORM_WINRT
    13 
    14 
    14 /* Forcibly disable UNICODE macro, since we manage this ourselves. */
    15 /* Forcibly disable UNICODE macro, since we manage this ourselves. */
    15 #ifdef UNICODE
    16 #ifdef UNICODE
    16 #undef UNICODE
    17 #undef UNICODE
    17 #endif
    18 #endif
   122         /* !!! FIXME: ?? case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP; */
   123         /* !!! FIXME: ?? case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP; */
   123         case ERROR_BUFFER_OVERFLOW: return PHYSFS_ERR_BAD_FILENAME;
   124         case ERROR_BUFFER_OVERFLOW: return PHYSFS_ERR_BAD_FILENAME;
   124         case ERROR_INVALID_NAME: return PHYSFS_ERR_BAD_FILENAME;
   125         case ERROR_INVALID_NAME: return PHYSFS_ERR_BAD_FILENAME;
   125         case ERROR_BAD_PATHNAME: return PHYSFS_ERR_BAD_FILENAME;
   126         case ERROR_BAD_PATHNAME: return PHYSFS_ERR_BAD_FILENAME;
   126         case ERROR_DIRECTORY: return PHYSFS_ERR_BAD_FILENAME;
   127         case ERROR_DIRECTORY: return PHYSFS_ERR_BAD_FILENAME;
   127         case ERROR_FILE_NOT_FOUND: return PHYSFS_ERR_NO_SUCH_PATH;
   128         case ERROR_FILE_NOT_FOUND: return PHYSFS_ERR_NOT_FOUND;
   128         case ERROR_PATH_NOT_FOUND: return PHYSFS_ERR_NO_SUCH_PATH;
   129         case ERROR_PATH_NOT_FOUND: return PHYSFS_ERR_NOT_FOUND;
   129         case ERROR_DELETE_PENDING: return PHYSFS_ERR_NO_SUCH_PATH;
   130         case ERROR_DELETE_PENDING: return PHYSFS_ERR_NOT_FOUND;
   130         case ERROR_INVALID_DRIVE: return PHYSFS_ERR_NO_SUCH_PATH;
   131         case ERROR_INVALID_DRIVE: return PHYSFS_ERR_NOT_FOUND;
   131         case ERROR_HANDLE_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
   132         case ERROR_HANDLE_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
   132         case ERROR_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
   133         case ERROR_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
   133         /* !!! FIXME: ?? case ENOTDIR: return PHYSFS_ERR_NO_SUCH_PATH; */
   134         /* !!! FIXME: ?? case ENOTDIR: return PHYSFS_ERR_NOT_FOUND; */
   134         /* !!! FIXME: ?? case EISDIR: return PHYSFS_ERR_NOT_A_FILE; */
   135         /* !!! FIXME: ?? case EISDIR: return PHYSFS_ERR_NOT_A_FILE; */
   135         case ERROR_WRITE_PROTECT: return PHYSFS_ERR_READ_ONLY;
   136         case ERROR_WRITE_PROTECT: return PHYSFS_ERR_READ_ONLY;
   136         case ERROR_LOCK_VIOLATION: return PHYSFS_ERR_BUSY;
   137         case ERROR_LOCK_VIOLATION: return PHYSFS_ERR_BUSY;
   137         case ERROR_SHARING_VIOLATION: return PHYSFS_ERR_BUSY;
   138         case ERROR_SHARING_VIOLATION: return PHYSFS_ERR_BUSY;
   138         case ERROR_CURRENT_DIRECTORY: return PHYSFS_ERR_BUSY;
   139         case ERROR_CURRENT_DIRECTORY: return PHYSFS_ERR_BUSY;
   169 
   170 
   170     if (stem)
   171     if (stem)
   171         stem(SEM_FAILCRITICALERRORS, &oldErrorMode);
   172         stem(SEM_FAILCRITICALERRORS, &oldErrorMode);
   172     else
   173     else
   173         oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
   174         oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
   174 
   175     
   175     /* Do detection. This may block if a disc is spinning up. */
   176     /* Do detection. This may block if a disc is spinning up. */
   176     for (i = 'A'; i <= 'Z'; i++)
   177     for (i = 'A'; i <= 'Z'; i++)
   177     {
   178     {
   178         DWORD tmp = 0;
   179         DWORD tmp = 0;
   179         drive[0] = (char) i;
   180         drive[0] = (char) i;
   367                 break;
   368                 break;
   368             ptr--;
   369             ptr--;
   369         } /* while */
   370         } /* while */
   370 
   371 
   371         if ((ptr == modpath) && (*ptr != '\\'))
   372         if ((ptr == modpath) && (*ptr != '\\'))
   372             __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR);  /* oh well. */
   373             PHYSFS_setErrorCode(PHYSFS_ERR_OTHER_ERROR);  /* oh well. */
   373         else
   374         else
   374         {
   375         {
   375             *(ptr+1) = '\0';  /* chop off filename. */
   376             *(ptr+1) = '\0';  /* chop off filename. */
   376             retval = unicodeToUtf8Heap(modpath);
   377             retval = unicodeToUtf8Heap(modpath);
   377         } /* else */
   378         } /* else */
   410         allocator.Free(utf8);
   411         allocator.Free(utf8);
   411         BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
   412         BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
   412     } /* if */
   413     } /* if */
   413 
   414 
   414     sprintf(retval, "%s\\%s\\%s\\", utf8, org, app);
   415     sprintf(retval, "%s\\%s\\%s\\", utf8, org, app);
       
   416     allocator.Free(utf8);
   415     return retval;
   417     return retval;
   416 } /* __PHYSFS_platformCalcPrefDir */
   418 } /* __PHYSFS_platformCalcPrefDir */
   417 
   419 
   418 
   420 
   419 char *__PHYSFS_platformCalcUserDir(void)
   421 char *__PHYSFS_platformCalcUserDir(void)
   441         /*
   443         /*
   442          * Should fail. Will write the size of the profile path in
   444          * Should fail. Will write the size of the profile path in
   443          *  psize. Also note that the second parameter can't be
   445          *  psize. Also note that the second parameter can't be
   444          *  NULL or the function fails.
   446          *  NULL or the function fails.
   445          */
   447          */
   446         rc = pGetDir(accessToken, &dummy, &psize);
   448     	rc = pGetDir(accessToken, &dummy, &psize);
   447         assert(!rc);  /* !!! FIXME: handle this gracefully. */
   449         assert(!rc);  /* !!! FIXME: handle this gracefully. */
   448         (void) rc;
   450         (void) rc;
   449 
   451 
   450         /* Allocate memory for the profile directory */
   452         /* Allocate memory for the profile directory */
   451         wstr = (LPWSTR) __PHYSFS_smallAlloc((psize + 1) * sizeof (WCHAR));
   453         wstr = (LPWSTR) __PHYSFS_smallAlloc((psize + 1) * sizeof (WCHAR));
   476 void *__PHYSFS_platformGetThreadID(void)
   478 void *__PHYSFS_platformGetThreadID(void)
   477 {
   479 {
   478     return ( (void *) ((size_t) GetCurrentThreadId()) );
   480     return ( (void *) ((size_t) GetCurrentThreadId()) );
   479 } /* __PHYSFS_platformGetThreadID */
   481 } /* __PHYSFS_platformGetThreadID */
   480 
   482 
   481 
       
   482 static int isSymlinkAttrs(const DWORD attr, const DWORD tag)
       
   483 {
       
   484     return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) &&
       
   485              (tag == PHYSFS_IO_REPARSE_TAG_SYMLINK) );
       
   486 } /* isSymlinkAttrs */
       
   487 
       
   488 
       
   489 void __PHYSFS_platformEnumerateFiles(const char *dirname,
   483 void __PHYSFS_platformEnumerateFiles(const char *dirname,
   490                                      int omitSymLinks,
       
   491                                      PHYSFS_EnumFilesCallback callback,
   484                                      PHYSFS_EnumFilesCallback callback,
   492                                      const char *origdir,
   485                                      const char *origdir,
   493                                      void *callbackdata)
   486                                      void *callbackdata)
   494 {
   487 {
   495     HANDLE dir = INVALID_HANDLE_VALUE;
   488     HANDLE dir = INVALID_HANDLE_VALUE;
   527     if (dir == INVALID_HANDLE_VALUE)
   520     if (dir == INVALID_HANDLE_VALUE)
   528         return;
   521         return;
   529 
   522 
   530     do
   523     do
   531     {
   524     {
   532         const DWORD attr = entw.dwFileAttributes;
       
   533         const DWORD tag = entw.dwReserved0;
       
   534         const WCHAR *fn = entw.cFileName;
   525         const WCHAR *fn = entw.cFileName;
   535         char *utf8;
   526         char *utf8;
   536 
   527 
   537         if ((fn[0] == '.') && (fn[1] == '\0'))
   528         if ((fn[0] == '.') && (fn[1] == '\0'))
   538             continue;
   529             continue;
   539         if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0'))
   530         if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0'))
   540             continue;
       
   541         if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
       
   542             continue;
   531             continue;
   543 
   532 
   544         utf8 = unicodeToUtf8Heap(fn);
   533         utf8 = unicodeToUtf8Heap(fn);
   545         if (utf8 != NULL)
   534         if (utf8 != NULL)
   546         {
   535         {
   718     if ( (rc == PHYSFS_INVALID_SET_FILE_POINTER) &&
   707     if ( (rc == PHYSFS_INVALID_SET_FILE_POINTER) &&
   719          (GetLastError() != NO_ERROR) )
   708          (GetLastError() != NO_ERROR) )
   720     {
   709     {
   721         BAIL_MACRO(errcodeFromWinApi(), 0);
   710         BAIL_MACRO(errcodeFromWinApi(), 0);
   722     } /* if */
   711     } /* if */
   723 
   712     
   724     return 1;  /* No error occured */
   713     return 1;  /* No error occured */
   725 } /* __PHYSFS_platformSeek */
   714 } /* __PHYSFS_platformSeek */
   726 
   715 
   727 
   716 
   728 PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
   717 PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
   874     retval = (PHYSFS_sint64) mktime(&tm);
   863     retval = (PHYSFS_sint64) mktime(&tm);
   875     BAIL_IF_MACRO(retval == -1, PHYSFS_ERR_OS_ERROR, -1);
   864     BAIL_IF_MACRO(retval == -1, PHYSFS_ERR_OS_ERROR, -1);
   876     return retval;
   865     return retval;
   877 } /* FileTimeToPhysfsTime */
   866 } /* FileTimeToPhysfsTime */
   878 
   867 
   879 int __PHYSFS_platformStat(const char *filename, int *exists, PHYSFS_Stat *stat)
   868 
       
   869 int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st)
   880 {
   870 {
   881     WIN32_FILE_ATTRIBUTE_DATA winstat;
   871     WIN32_FILE_ATTRIBUTE_DATA winstat;
   882     WCHAR *wstr = NULL;
   872     WCHAR *wstr = NULL;
   883     DWORD err = 0;
   873     DWORD err = 0;
   884     BOOL rc = 0;
   874     BOOL rc = 0;
   885 
   875 
   886     UTF8_TO_UNICODE_STACK_MACRO(wstr, filename);
   876     UTF8_TO_UNICODE_STACK_MACRO(wstr, filename);
   887     BAIL_IF_MACRO(!wstr, PHYSFS_ERR_OUT_OF_MEMORY, 0);
   877     BAIL_IF_MACRO(!wstr, PHYSFS_ERR_OUT_OF_MEMORY, 0);
   888     rc = GetFileAttributesExW(wstr, GetFileExInfoStandard, &winstat);
   878     rc = GetFileAttributesExW(wstr, GetFileExInfoStandard, &winstat);
   889     err = (!rc) ? GetLastError() : 0;
   879     err = (!rc) ? GetLastError() : 0;
   890     *exists = ((err != ERROR_FILE_NOT_FOUND) && (err != ERROR_PATH_NOT_FOUND));
       
   891     __PHYSFS_smallFree(wstr);
   880     __PHYSFS_smallFree(wstr);
   892     BAIL_IF_MACRO(!rc, errcodeFromWinApiError(err), 0);
   881     BAIL_IF_MACRO(!rc, errcodeFromWinApiError(err), 0);
   893 
   882 
   894     stat->modtime = FileTimeToPhysfsTime(&winstat.ftLastWriteTime);
   883     st->modtime = FileTimeToPhysfsTime(&winstat.ftLastWriteTime);
   895     stat->accesstime = FileTimeToPhysfsTime(&winstat.ftLastAccessTime);
   884     st->accesstime = FileTimeToPhysfsTime(&winstat.ftLastAccessTime);
   896     stat->createtime = FileTimeToPhysfsTime(&winstat.ftCreationTime);
   885     st->createtime = FileTimeToPhysfsTime(&winstat.ftCreationTime);
   897 
   886 
   898     if(winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
   887     if(winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
   899     {
   888     {
   900         stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
   889         st->filetype = PHYSFS_FILETYPE_DIRECTORY;
   901         stat->filesize = 0;
   890         st->filesize = 0;
   902     } /* if */
   891     } /* if */
   903 
   892 
   904     else if(winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE))
   893     else if(winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE))
   905     {
   894     {
   906         /* !!! FIXME: what are reparse points? */
   895         /* !!! FIXME: what are reparse points? */
   907         stat->filetype = PHYSFS_FILETYPE_OTHER;
   896         st->filetype = PHYSFS_FILETYPE_OTHER;
   908         /* !!! FIXME: don't rely on this */
   897         /* !!! FIXME: don't rely on this */
   909         stat->filesize = 0;
   898         st->filesize = 0;
   910     } /* else if */
   899     } /* else if */
   911 
   900 
   912     /* !!! FIXME: check for symlinks on Vista. */
   901     /* !!! FIXME: check for symlinks on Vista. */
   913 
   902 
   914     else
   903     else
   915     {
   904     {
   916         stat->filetype = PHYSFS_FILETYPE_REGULAR;
   905         st->filetype = PHYSFS_FILETYPE_REGULAR;
   917         stat->filesize = (((PHYSFS_uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow;
   906         st->filesize = (((PHYSFS_uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow;
   918     } /* else */
   907     } /* else */
   919 
   908 
   920     stat->readonly = ((winstat.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
   909     st->readonly = ((winstat.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
   921 
   910 
   922     return 1;
   911     return 1;
   923 } /* __PHYSFS_platformStat */
   912 } /* __PHYSFS_platformStat */
   924 
   913 
   925 
   914 
   928 {
   917 {
   929     return 0;  /* just use malloc() and friends. */
   918     return 0;  /* just use malloc() and friends. */
   930 } /* __PHYSFS_platformSetDefaultAllocator */
   919 } /* __PHYSFS_platformSetDefaultAllocator */
   931 
   920 
   932 #endif  /* PHYSFS_PLATFORM_WINDOWS */
   921 #endif  /* PHYSFS_PLATFORM_WINDOWS */
       
   922 #endif  /* PHYSFS_PLATFORM_WINRT */
   933 
   923 
   934 /* end of windows.c ... */
   924 /* end of windows.c ... */
   935 
   925 
   936 
   926