⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32.c

📁 嵌入式环境下的GUI
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Win32 support routines for PhysicsFS. * * Please see the file LICENSE in the source's root directory. * *  This file written by Ryan C. Gordon, and made sane by Gregory S. Read. */#if HAVE_CONFIG_H#  include <config.h>#endif#ifdef WIN32#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <time.h>#define __PHYSICSFS_INTERNAL__#include "physfs_internal.h"#if (defined _MSC_VER)    #define alloca(x) _alloca(x)#elif (defined MINGW)  /* scary...hopefully this is okay. */    #define alloca(x) __builtin_alloca(x) #endif#define LOWORDER_UINT64(pos)       (PHYSFS_uint32)(pos & 0x00000000FFFFFFFF)#define HIGHORDER_UINT64(pos)      (PHYSFS_uint32)(pos & 0xFFFFFFFF00000000)/* GetUserProfileDirectory() is only available on >= NT4 (no 9x/ME systems!) */typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (      HANDLE hToken,      LPTSTR lpProfileDir,      LPDWORD lpcchSize);/* GetFileAttributesEx() is only available on >= Win98 or WinNT4 ... */typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETFILEATTRIBUTESEX) (      LPCTSTR lpFileName,      GET_FILEEX_INFO_LEVELS fInfoLevelId,      LPVOID lpFileInformation);typedef struct{    HANDLE handle;    int readonly;} win32file;const char *__PHYSFS_platformDirSeparator = "\\";static LPFNGETFILEATTRIBUTESEX pGetFileAttributesEx = NULL;static HANDLE libKernel32 = NULL;static char *userDir = NULL;/* * Users without the platform SDK don't have this defined.  The original docs *  for SetFilePointer() just said to compare with 0xFFFFFFFF, so this should *  work as desired */#ifndef INVALID_SET_FILE_POINTER#  define INVALID_SET_FILE_POINTER  0xFFFFFFFF#endif/* just in case... */#ifndef INVALID_FILE_ATTRIBUTES#  define INVALID_FILE_ATTRIBUTES   0xFFFFFFFF#endif/* * Figure out what the last failing Win32 API call was, and *  generate a human-readable string for the error message. * * The return value is a static buffer that is overwritten with *  each call to this function. */static const char *win32strerror(void){    static TCHAR msgbuf[255];    TCHAR *ptr = msgbuf;    FormatMessage(        FORMAT_MESSAGE_FROM_SYSTEM |        FORMAT_MESSAGE_IGNORE_INSERTS,        NULL,        GetLastError(),        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */        msgbuf,        sizeof (msgbuf) / sizeof (TCHAR),        NULL     );        /* chop off newlines. */    for (ptr = msgbuf; *ptr; ptr++)    {        if ((*ptr == '\n') || (*ptr == '\r'))        {            *ptr = ' ';            break;        } /* if */    } /* for */    return((const char *) msgbuf);} /* win32strerror */static char *getExePath(const char *argv0){    DWORD buflen;    int success = 0;    char *ptr = NULL;    char *retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1));    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);    retval[0] = '\0';    buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);    if (buflen <= 0)        __PHYSFS_setError(win32strerror());    else    {        retval[buflen] = '\0';  /* does API always null-terminate this? */            /* make sure the string was not truncated. */        if (__PHYSFS_platformStricmp(&retval[buflen - 4], ".exe") != 0)            __PHYSFS_setError(ERR_GETMODFN_TRUNC);        else        {            ptr = strrchr(retval, '\\');            if (ptr == NULL)                __PHYSFS_setError(ERR_GETMODFN_NO_DIR);            else            {                *(ptr + 1) = '\0';  /* chop off filename. */                success = 1;            } /* else */        } /* else */    } /* else */    /* if any part of the previous approach failed, try SearchPath()... */    if (!success)    {        if (argv0 == NULL)            __PHYSFS_setError(ERR_ARGV0_IS_NULL);        else        {            buflen = SearchPath(NULL, argv0, NULL, MAX_PATH+1, retval, &ptr);            if (buflen == 0)                __PHYSFS_setError(win32strerror());            else if (buflen > MAX_PATH)                __PHYSFS_setError(ERR_SEARCHPATH_TRUNC);            else                success = 1;        } /* else */    } /* if */    if (!success)    {        free(retval);        return(NULL);  /* physfs error message will be set, above. */    } /* if */    /* free up the bytes we didn't actually use. */    ptr = (char *) realloc(retval, strlen(retval) + 1);    if (ptr != NULL)        retval = ptr;    return(retval);   /* w00t. */} /* getExePath *//* * Try to make use of GetUserProfileDirectory(), which isn't available on *  some common variants of Win32. If we can't use this, we just punt and *  use the physfs base dir for the user dir, too. * * On success, module-scope variable (userDir) will have a pointer to *  a malloc()'d string of the user's profile dir, and a non-zero value is *  returned. If we can't determine the profile dir, (userDir) will *  be NULL, and zero is returned. */static int determineUserDir(void){    DWORD psize = 0;    char dummy[1];    BOOL rc = 0;    HANDLE processHandle;            /* Current process handle */    HANDLE accessToken = NULL;       /* Security handle to process */    LPFNGETUSERPROFILEDIR GetUserProfileDirectory;    HMODULE lib;    assert(userDir == NULL);    /*     * GetUserProfileDirectory() is only available on NT 4.0 and later.     *  This means Win95/98/ME (and CE?) users have to do without, so for     *  them, we'll default to the base directory when we can't get the     *  function pointer.     */    lib = LoadLibrary("userenv.dll");    if (lib)    {        /* !!! FIXME: Handle Unicode? */        GetUserProfileDirectory = (LPFNGETUSERPROFILEDIR)                              GetProcAddress(lib, "GetUserProfileDirectoryA");        if (GetUserProfileDirectory)        {            processHandle = GetCurrentProcess();            if (OpenProcessToken(processHandle, TOKEN_QUERY, &accessToken))            {                /*                 * Should fail. Will write the size of the profile path in                 *  psize. Also note that the second parameter can't be                 *  NULL or the function fails.                 */                rc = GetUserProfileDirectory(accessToken, dummy, &psize);                assert(!rc);  /* success?! */                /* Allocate memory for the profile directory */                userDir = (char *) malloc(psize);                if (userDir != NULL)                {                    if (!GetUserProfileDirectory(accessToken, userDir, &psize))                    {                        free(userDir);                        userDir = NULL;                    } /* if */                } /* else */            } /* if */            CloseHandle(accessToken);        } /* if */        FreeLibrary(lib);    } /* if */    if (userDir == NULL)  /* couldn't get profile for some reason. */    {        /* Might just be a non-NT system; resort to the basedir. */        userDir = getExePath(NULL);        BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* STILL failed?! */    } /* if */    return(1);  /* We made it: hit the showers. */} /* determineUserDir */static BOOL mediaInDrive(const char *drive){    UINT oldErrorMode;    DWORD tmp;    BOOL retval;    /* Prevent windows warning message to appear when checking media size */    oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);        /* If this function succeeds, there's media in the drive */    retval = GetVolumeInformation(drive, NULL, 0, NULL, NULL, &tmp, NULL, 0);    /* Revert back to old windows error handler */    SetErrorMode(oldErrorMode);    return(retval);} /* mediaInDrive */char **__PHYSFS_platformDetectAvailableCDs(void){    char **retval = (char **) malloc(sizeof (char *));    int cd_count = 1;  /* We count the NULL entry. */    char drive_str[4] = "x:\\";    for (drive_str[0] = 'A'; drive_str[0] <= 'Z'; drive_str[0]++)    {        if (GetDriveType(drive_str) == DRIVE_CDROM && mediaInDrive(drive_str))        {            char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));            if (tmp)            {                retval = tmp;                retval[cd_count - 1] = (char *) malloc(4);                if (retval[cd_count - 1])                {                    strcpy(retval[cd_count - 1], drive_str);                    cd_count++;                } /* if */            } /* if */        } /* if */    } /* for */    retval[cd_count - 1] = NULL;    return(retval);} /* __PHYSFS_detectAvailableCDs */char *__PHYSFS_platformCalcBaseDir(const char *argv0){    if ((argv0 != NULL) && (strchr(argv0, '\\') != NULL))        return(NULL); /* default behaviour can handle this. */    return(getExePath(argv0));} /* __PHYSFS_platformCalcBaseDir */char *__PHYSFS_platformGetUserName(void){    DWORD bufsize = 0;    LPTSTR retval = NULL;    if (GetUserName(NULL, &bufsize) == 0)  /* This SHOULD fail. */    {        retval = (LPTSTR) malloc(bufsize);        BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);        if (GetUserName(retval, &bufsize) == 0)  /* ?! */        {            __PHYSFS_setError(win32strerror());            free(retval);            retval = NULL;        } /* if */    } /* if */    return((char *) retval);} /* __PHYSFS_platformGetUserName */char *__PHYSFS_platformGetUserDir(void){    char *retval = (char *) malloc(strlen(userDir) + 1);    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);    strcpy(retval, userDir); /* calculated at init time. */    return(retval);} /* __PHYSFS_platformGetUserDir */PHYSFS_uint64 __PHYSFS_platformGetThreadID(void){    return((PHYSFS_uint64) GetCurrentThreadId());} /* __PHYSFS_platformGetThreadID *//* ...make this Cygwin AND Visual C friendly... */int __PHYSFS_platformStricmp(const char *x, const char *y){#if (defined _MSC_VER)    return(stricmp(x, y));#else    int ux, uy;    do    {        ux = toupper((int) *x);        uy = toupper((int) *y);        if (ux > uy)            return(1);        else if (ux < uy)            return(-1);        x++;        y++;    } while ((ux) && (uy));    return(0);#endif} /* __PHYSFS_platformStricmp */int __PHYSFS_platformExists(const char *fname){    BAIL_IF_MACRO(GetFileAttributes(fname) == INVALID_FILE_ATTRIBUTES,                  win32strerror(), 0);    return(1);} /* __PHYSFS_platformExists */int __PHYSFS_platformIsSymLink(const char *fname){    return(0);  /* no symlinks on win32. */} /* __PHYSFS_platformIsSymlink */int __PHYSFS_platformIsDirectory(const char *fname){    return((GetFileAttributes(fname) & FILE_ATTRIBUTE_DIRECTORY) != 0);} /* __PHYSFS_platformIsDirectory */char *__PHYSFS_platformCvtToDependent(const char *prepend,                                      const char *dirName,                                      const char *append){    int len = ((prepend) ? strlen(prepend) : 0) +              ((append) ? strlen(append) : 0) +              strlen(dirName) + 1;    char *retval = malloc(len);    char *p;    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);    if (prepend)        strcpy(retval, prepend);    else        retval[0] = '\0';    strcat(retval, dirName);    if (append)        strcat(retval, append);    for (p = strchr(retval, '/'); p != NULL; p = strchr(p + 1, '/'))        *p = '\\';    return(retval);} /* __PHYSFS_platformCvtToDependent *//* Much like my college days, try to sleep for 10 milliseconds at a time... */void __PHYSFS_platformTimeslice(void){    Sleep(10);} /* __PHYSFS_platformTimeslice */LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,                                                  int omitSymLinks){    LinkedStringList *retval = NULL, *p = NULL;    HANDLE dir;    WIN32_FIND_DATA ent;    char *SearchPath;    size_t len = strlen(dirname);    /* Allocate a new string for path, maybe '\\', "*", and NULL terminator */    SearchPath = (char *) alloca(len + 3);    BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL);    /* Copy current dirname */    strcpy(SearchPath, dirname);    /* if there's no '\\' at the end of the path, stick one in there. */    if (SearchPath[len - 1] != '\\')    {        SearchPath[len++] = '\\';        SearchPath[len] = '\0';    } /* if */    /* Append the "*" to the end of the string */    strcat(SearchPath, "*");    dir = FindFirstFile(SearchPath, &ent);    BAIL_IF_MACRO(dir == INVALID_HANDLE_VALUE, win32strerror(), NULL);    do    {        if (strcmp(ent.cFileName, ".") == 0)            continue;        if (strcmp(ent.cFileName, "..") == 0)            continue;        retval = __PHYSFS_addToLinkedStringList(retval, &p, ent.cFileName, -1);    } while (FindNextFile(dir, &ent) != 0);    FindClose(dir);    return(retval);} /* __PHYSFS_platformEnumerateFiles */char *__PHYSFS_platformCurrentDir(void){    LPTSTR retval;    DWORD buflen = 0;    buflen = GetCurrentDirectory(buflen, NULL);    retval = (LPTSTR) malloc(sizeof (TCHAR) * (buflen + 2));    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);    GetCurrentDirectory(buflen, retval);    if (retval[buflen - 2] != '\\')        strcat(retval, "\\");    return((char *) retval);} /* __PHYSFS_platformCurrentDir *//* this could probably use a cleanup. */char *__PHYSFS_platformRealPath(const char *path){    char *retval = NULL;    char *p = NULL;    BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL);    BAIL_IF_MACRO(*path == '\0', ERR_INVALID_ARGUMENT, NULL);    retval = (char *) malloc(MAX_PATH);    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);        /*         * If in \\server\path format, it's already an absolute path.         *  We'll need to check for "." and ".." dirs, though, just in case.         */    if ((path[0] == '\\') && (path[1] == '\\'))        strcpy(retval, path);    else    {        char *currentDir = __PHYSFS_platformCurrentDir();        if (currentDir == NULL)        {            free(retval);            BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);        } /* if */        if (path[1] == ':')   /* drive letter specified? */        {            /*             * Apparently, "D:mypath" is the same as "D:\\mypath" if             *  D: is not the current drive. However, if D: is the             *  current drive, then "D:mypath" is a relative path. Ugh.             */            if (path[2] == '\\')  /* maybe an absolute path? */                strcpy(retval, path);            else  /* definitely an absolute path. */            {                if (path[0] == currentDir[0]) /* current drive; relative. */                {                    strcpy(retval, currentDir);                    strcat(retval, path + 2);                } /* if */                else  /* not current drive; absolute. */                {                    retval[0] = path[0];                    retval[1] = ':';                    retval[2] = '\\';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -