From DONOTREPLY at icculus.org Sat Sep 15 02:05:37 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 15 Sep 2007 02:05:37 -0400 Subject: r335 - trunk Message-ID: <20070915060537.3538.qmail@icculus.org> Author: icculus Date: 2007-09-15 02:05:37 -0400 (Sat, 15 Sep 2007) New Revision: 335 Modified: trunk/gui_gtkplus2.c Log: Added a "browse" button for a selector dialog to the GTK+ install path page. Thanks to Scott Brooks for the patch. Modified: trunk/gui_gtkplus2.c =================================================================== --- trunk/gui_gtkplus2.c 2007-07-02 09:27:00 UTC (rev 334) +++ trunk/gui_gtkplus2.c 2007-09-15 06:05:37 UTC (rev 335) @@ -53,6 +53,8 @@ static GtkWidget *progresslabel = NULL; static GtkWidget *finallabel = NULL; static GtkWidget *componentlabel = NULL; +static GtkWidget *dirselect = NULL; +static GtkWidget *browse = NULL; static volatile enum { @@ -151,7 +153,21 @@ } // else } // signal_clicked +static void signal_browse_clicked(GtkButton *_button, gpointer data) +{ + gtk_widget_show(dirselect); +} +static void dirselect_ok_sel( GtkWidget *w, GtkFileSelection *fs ) +{ + GtkComboBox *combo = GTK_COMBO_BOX(destination); + const char *path = gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)); + gtk_combo_box_prepend_text(combo, path); + gtk_combo_box_set_active (combo, 0); + gtk_widget_hide(dirselect); +} + + static uint8 MojoGui_gtkplus2_priority(void) { // !!! FIXME: This would disallow gtkfb, gtk+/mac, gtk+windows, etc... @@ -262,7 +278,9 @@ static GtkWidget *create_button(GtkWidget *box, const char *iconname, - const char *text) + const char *text, + void (*signal_callback) + (GtkButton *button, gpointer data)) { // !!! FIXME: gtk_button_set_use_stock()? GtkWidget *button = gtk_button_new(); @@ -281,7 +299,7 @@ gtk_widget_show (label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(signal_clicked), NULL); + GTK_SIGNAL_FUNC(signal_callback), NULL); return button; } // create_button @@ -328,10 +346,10 @@ gtk_box_pack_start(GTK_BOX(box), widget, FALSE, FALSE, 0); box = widget; - cancel = create_button(box, "gtk-cancel", entry->_("Cancel")); - back = create_button(box, "gtk-go-back", entry->_("Back")); - next = create_button(box, "gtk-go-forward", entry->_("Next")); - finish = create_button(box, "gtk-goto-last", entry->_("Finish")); + cancel = create_button(box, "gtk-cancel", entry->_("Cancel"), signal_clicked); + back = create_button(box, "gtk-go-back", entry->_("Back"), signal_clicked); + next = create_button(box, "gtk-go-forward", entry->_("Next"), signal_clicked); + finish = create_button(box, "gtk-goto-last", entry->_("Finish"), signal_clicked); gtk_widget_hide(finish); // !!! FIXME: intro page. @@ -375,8 +393,17 @@ gtk_widget_show(destination); gtk_container_add(GTK_CONTAINER(alignment), destination); gtk_box_pack_start(GTK_BOX(box), alignment, FALSE, TRUE, 0); + browse = create_button(box, "fileopen", entry->_("Browse"), signal_browse_clicked); gtk_container_add(GTK_CONTAINER(notebook), box); + // Install Path selection + dirselect = gtk_file_selection_new("Install Path"); + g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (dirselect)->ok_button), + "clicked", G_CALLBACK (dirselect_ok_sel), (gpointer) dirselect); + g_signal_connect_swapped (G_OBJECT (GTK_FILE_SELECTION (dirselect)->cancel_button), + "clicked", G_CALLBACK (gtk_widget_destroy), + G_OBJECT (dirselect)); + // !!! FIXME: progress page. box = gtk_vbox_new(FALSE, 0); gtk_widget_show(box); From DONOTREPLY at icculus.org Thu Sep 20 00:45:49 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 00:45:49 -0400 Subject: r336 - trunk Message-ID: <20070920044549.19426.qmail@icculus.org> Author: icculus Date: 2007-09-20 00:45:49 -0400 (Thu, 20 Sep 2007) New Revision: 336 Modified: trunk/universal.h Log: Improved STUBBED macro a little. Modified: trunk/universal.h =================================================================== --- trunk/universal.h 2007-09-15 06:05:37 UTC (rev 335) +++ trunk/universal.h 2007-09-20 04:45:49 UTC (rev 336) @@ -310,18 +310,17 @@ #endif #endif // DOXYGEN_SHOULD_IGNORE_THIS -#if 1 +#ifndef DOXYGEN_SHOULD_IGNORE_THIS #define STUBBED(x) \ -{ \ +do { \ static boolean seen_this = false; \ if (!seen_this) \ { \ seen_this = true; \ - fprintf(stderr, "STUBBED: %s at %s:%d\n", x, __FILE__, __LINE__); \ + fprintf(stderr, "STUBBED: %s at %s (%s:%d)\n", x, __FUNCTION__, \ + __FILE__, __LINE__); \ } \ -} -#else -#define STUBBED(x) +} while (false) #endif #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) ) From DONOTREPLY at icculus.org Thu Sep 20 00:46:10 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 00:46:10 -0400 Subject: r337 - trunk Message-ID: <20070920044610.19608.qmail@icculus.org> Author: icculus Date: 2007-09-20 00:46:09 -0400 (Thu, 20 Sep 2007) New Revision: 337 Modified: trunk/gui_macosx.c Log: Minor STUBBED cleanup. Modified: trunk/gui_macosx.c =================================================================== --- trunk/gui_macosx.c 2007-09-20 04:45:49 UTC (rev 336) +++ trunk/gui_macosx.c 2007-09-20 04:46:09 UTC (rev 337) @@ -199,7 +199,7 @@ int percent, const char *item) { // !!! FIXME: write me. - STUBBED(__FUNCTION__) + STUBBED("macosx progress"); return 1; } // MojoGui_macosx_progress @@ -207,7 +207,7 @@ static void MojoGui_macosx_final(const char *msg) { // !!! FIXME: write me. - STUBBED(__FUNCTION__) + STUBBED("macosx final"); } // MojoGui_macosx_final // end of gui_macosx.c ... From DONOTREPLY at icculus.org Thu Sep 20 02:56:16 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 02:56:16 -0400 Subject: r338 - trunk Message-ID: <20070920065616.21653.qmail@icculus.org> Author: icculus Date: 2007-09-20 02:56:15 -0400 (Thu, 20 Sep 2007) New Revision: 338 Modified: trunk/gui_macosx.c Log: Patched to compile on Mac OS X. Modified: trunk/gui_macosx.c =================================================================== --- trunk/gui_macosx.c 2007-09-20 04:46:09 UTC (rev 337) +++ trunk/gui_macosx.c 2007-09-20 06:56:15 UTC (rev 338) @@ -130,7 +130,7 @@ } // do_prompt -static boolean MojoGui_macosx_promptyn(const char *title, const char *text +static boolean MojoGui_macosx_promptyn(const char *title, const char *text, boolean defval) { return do_prompt(title, text, defval, entry->_("Yes"), entry->_("No")); From DONOTREPLY at icculus.org Thu Sep 20 02:57:04 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 02:57:04 -0400 Subject: r339 - trunk Message-ID: <20070920065704.21921.qmail@icculus.org> Author: icculus Date: 2007-09-20 02:57:04 -0400 (Thu, 20 Sep 2007) New Revision: 339 Modified: trunk/fileio.c trunk/platform.h trunk/platform_unix.c Log: Some initial work on abstracting Unix-specific bits from fileio.c ... Modified: trunk/fileio.c =================================================================== --- trunk/fileio.c 2007-09-20 06:56:15 UTC (rev 338) +++ trunk/fileio.c 2007-09-20 06:57:04 UTC (rev 339) @@ -305,16 +305,15 @@ #include #include #include -#include typedef struct DirStack { - DIR *dir; + void *dir; char *basepath; struct DirStack *next; } DirStack; -static void pushDirStack(DirStack **_stack, const char *basepath, DIR *dir) +static void pushDirStack(DirStack **_stack, const char *basepath, void *dir) { DirStack *stack = (DirStack *) xmalloc(sizeof (DirStack)); stack->dir = dir; @@ -330,7 +329,7 @@ { DirStack *next = stack->next; if (stack->dir) - closedir(stack->dir); + MojoPlatform_closedir(stack->dir); free(stack->basepath); free(stack); *_stack = next; @@ -353,12 +352,12 @@ static boolean MojoArchive_dir_enumerate(MojoArchive *ar) { MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque; - DIR *dir = NULL; + void *dir = NULL; freeDirStack(&inst->dirs); MojoArchive_resetEntry(&ar->prevEnum); - dir = opendir(inst->base); + dir = MojoPlatform_opendir(inst->base); if (dir != NULL) pushDirStack(&inst->dirs, inst->base, dir); @@ -370,28 +369,29 @@ { struct stat statbuf; char *fullpath = NULL; - struct dirent *dent = NULL; + char *dent = NULL; // "dent" == "directory entry" MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque; + const char *basepath = inst->dirs->basepath; MojoArchive_resetEntry(&ar->prevEnum); if (inst->dirs == NULL) return NULL; - dent = readdir(inst->dirs->dir); + // if readdir fails, it's end of dir (!!! FIXME: what about i/o failures?) + dent = MojoPlatform_readdir(inst->dirs->dir); if (dent == NULL) // end of dir? { popDirStack(&inst->dirs); return MojoArchive_dir_enumNext(ar); // try higher level in tree. } // if - if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0)) - return MojoArchive_dir_enumNext(ar); // skip these. + // MojoPlatform layer shouldn't return "." or ".." paths. + assert((strcmp(dent, ".") != 0) && (strcmp(dent, "..") != 0)); - fullpath = (char *) xmalloc(strlen(inst->dirs->basepath) + - strlen(dent->d_name) + 2); - - sprintf(fullpath, "%s/%s", inst->dirs->basepath, dent->d_name); + fullpath = (char *) xmalloc(strlen(basepath) + strlen(dent) + 2); + sprintf(fullpath, "%s/%s", basepath, dent); + free(dent); ar->prevEnum.filename = xstrdup(fullpath + strlen(inst->base) + 1); if (lstat(fullpath, &statbuf) == -1) @@ -424,7 +424,7 @@ else if (S_ISDIR(statbuf.st_mode)) { - DIR *dir = opendir(fullpath); + void *dir = MojoPlatform_opendir(fullpath); ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR; if (dir == NULL) { Modified: trunk/platform.h =================================================================== --- trunk/platform.h 2007-09-20 06:56:15 UTC (rev 338) +++ trunk/platform.h 2007-09-20 06:57:04 UTC (rev 339) @@ -81,6 +81,24 @@ // !!! FIXME: comment me. char *MojoPlatform_findMedia(const char *uniquefile); +// Enumerate a directory. Returns an opaque pointer that can be used with +// repeated calls to MojoPlatform_readdir() to enumerate the names of +// directory entries. Returns NULL on error. Non-NULL values should be passed +// to MojoPlatform_closedir() for cleanup when you are done with them. +void *MojoPlatform_opendir(const char *dirname); + +// Get the next entry in the directory. (dirhandle) is an opaque pointer +// returned by MojoPlatform_opendir(). Returns NULL if we're at the end of +// the directory, or a null-terminated UTF-8 string otherwise. The order of +// results are not guaranteed, and may change between two iterations. +// Caller must free returned string! +char *MojoPlatform_readdir(void *dirhandle); + +// Clean up resources used by a directory enumeration. (dirhandle) is an +// opaque pointer returned by MojoPlatform_opendir(), and becomes invalid +// after this call. +void MojoPlatform_closedir(void *dirhandle); + // Convert a string into a permissions bitmask. On Unix, this is currently // expected to be an octal string like "0755", but may except other forms // in the future, and other platforms may need to interpret permissions Modified: trunk/platform_unix.c =================================================================== --- trunk/platform_unix.c 2007-09-20 06:56:15 UTC (rev 338) +++ trunk/platform_unix.c 2007-09-20 06:57:04 UTC (rev 339) @@ -24,6 +24,7 @@ #include #include #include +#include #if MOJOSETUP_HAVE_SYS_UCRED_H # ifdef MOJOSETUP_HAVE_MNTENT_H @@ -549,6 +550,39 @@ } // MojoPlatform_isdir +void *MojoPlatform_opendir(const char *dirname) +{ + return opendir(dirname); +} // MojoPlatform_opendir + + +char *MojoPlatform_readdir(void *_dirhandle) +{ + DIR *dirhandle = (DIR *) _dirhandle; + struct dirent *dent = NULL; + + while ((dent = readdir(dirhandle)) != NULL) + { + if (strcmp(dent->d_name, ".") == 0) + continue; // skip these. + + else if (strcmp(dent->d_name, "..") == 0) + continue; // skip these, too. + + else + break; // found a valid entry, go on. + } // while + + return ((dent) ? xstrdup(dent->d_name) : NULL); +} // MojoPlatform_readdir + + +void MojoPlatform_closedir(void *dirhandle) +{ + closedir((DIR *) dirhandle); +} // MojoPlatform_closedir + + boolean MojoPlatform_perms(const char *fname, uint16 *p) { boolean retval = false; From DONOTREPLY at icculus.org Thu Sep 20 04:34:56 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 04:34:56 -0400 Subject: r340 - trunk Message-ID: <20070920083456.30036.qmail@icculus.org> Author: icculus Date: 2007-09-20 04:34:55 -0400 (Thu, 20 Sep 2007) New Revision: 340 Modified: trunk/fileio.c trunk/lua_glue.c trunk/mojosetup.c trunk/platform.h trunk/platform_unix.c Log: Reworked the rest of the Unix-specific bits out of fileio.c ... untested! Modified: trunk/fileio.c =================================================================== --- trunk/fileio.c 2007-09-20 06:57:04 UTC (rev 339) +++ trunk/fileio.c 2007-09-20 08:34:55 UTC (rev 340) @@ -6,8 +6,6 @@ * This file written by Ryan C. Gordon. */ -#include // !!! FIXME: unix dependency for stat(). - #include "fileio.h" #include "platform.h" @@ -88,7 +86,7 @@ { boolean retval = false; uint32 start = MojoPlatform_ticks(); - FILE *out = NULL; + void *out = NULL; boolean iofailure = false; int64 flen = 0; int64 bw = 0; @@ -120,7 +118,11 @@ MojoPlatform_unlink(fname); if (!iofailure) - out = fopen(fname, "wb"); + { + const uint32 flags = MOJOFILE_WRITE|MOJOFILE_CREATE|MOJOFILE_TRUNCATE; + const uint16 mode = MojoPlatform_defaultFilePerms(); + out = MojoPlatform_open(fname, flags, mode); + } // if if (out != NULL) { @@ -141,7 +143,7 @@ iofailure = true; else { - if (fwrite(scratchbuf_128k, br, 1, out) != 1) + if (MojoPlatform_write(out, scratchbuf_128k, br) != br) iofailure = true; else { @@ -159,7 +161,7 @@ } // if } // while - if (fclose(out) != 0) + if (MojoPlatform_close(out) != 0) iofailure = true; if (iofailure) @@ -204,7 +206,7 @@ typedef struct { - FILE *handle; + void *handle; char *path; } MojoInputFileInstance; @@ -217,43 +219,25 @@ static int64 MojoInput_file_read(MojoInput *io, void *buf, uint32 bufsize) { MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque; - return (int64) fread(buf, 1, bufsize, inst->handle); + return MojoPlatform_read(inst->handle, buf, bufsize); } // MojoInput_file_read static boolean MojoInput_file_seek(MojoInput *io, uint64 pos) { MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque; -#if 1 - rewind(inst->handle); - while (pos) - { - // do in a loop to make sure we seek correctly in > 2 gig files. - if (fseek(inst->handle, (long) (pos & 0x7FFFFFFF), SEEK_CUR) == -1) - return false; - pos -= (pos & 0x7FFFFFFF); - } // while - return true; -#else - return (fseeko(inst->handle, pos, SEEK_SET) == 0); -#endif + return (MojoPlatform_seek(inst->handle, pos, MOJOSEEK_SET) == pos); } // MojoInput_file_seek static int64 MojoInput_file_tell(MojoInput *io) { MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque; -// return (int64) ftello(inst->handle); - STUBBED("ftell is 32 bit!\n"); - return (int64) ftell(inst->handle); + return MojoPlatform_tell(inst->handle); } // MojoInput_file_tell static int64 MojoInput_file_length(MojoInput *io) { MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque; - int fd = fileno(inst->handle); - struct stat statbuf; - if ((fd == -1) || (fstat(fd, &statbuf) == -1)) - return -1; - return((int64) statbuf.st_size); + return MojoPlatform_flen(inst->handle); } // MojoInput_file_length static MojoInput *MojoInput_file_duplicate(MojoInput *io) @@ -265,7 +249,7 @@ static void MojoInput_file_close(MojoInput *io) { MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque; - fclose(inst->handle); + MojoPlatform_close(inst->handle); free(inst->path); free(inst); free(io); @@ -274,9 +258,9 @@ MojoInput *MojoInput_newFromFile(const char *path) { MojoInput *io = NULL; - FILE *f = NULL; + void *f = NULL; - f = fopen(path, "rb"); + f = MojoPlatform_open(path, MOJOFILE_READ, 0); if (f != NULL) { MojoInputFileInstance *inst; @@ -301,11 +285,6 @@ // MojoArchives from directories on the OS filesystem. -// !!! FIXME: abstract the unixy bits into the platform/ dir. -#include -#include -#include - typedef struct DirStack { void *dir; @@ -367,7 +346,7 @@ static const MojoArchiveEntry *MojoArchive_dir_enumNext(MojoArchive *ar) { - struct stat statbuf; + uint16 perms = 0644; //(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); char *fullpath = NULL; char *dent = NULL; // "dent" == "directory entry" MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque; @@ -392,48 +371,53 @@ fullpath = (char *) xmalloc(strlen(basepath) + strlen(dent) + 2); sprintf(fullpath, "%s/%s", basepath, dent); free(dent); + ar->prevEnum.filename = xstrdup(fullpath + strlen(inst->base) + 1); + ar->prevEnum.filesize = 0; + ar->prevEnum.type = MOJOARCHIVE_ENTRY_UNKNOWN; - if (lstat(fullpath, &statbuf) == -1) - ar->prevEnum.type = MOJOARCHIVE_ENTRY_UNKNOWN; - else + // We currently force the perms from physical files, since CDs on + // Linux tend to mark every files as executable and read-only. If you + // want to install something with specific permissions, wrap it in a + // tarball, or use Setup.File.permissions, or return a permissions + // string from Setup.File.filter. + //MojoPlatform_perms(fullpath, &perms); + ar->prevEnum.perms = perms; + + if (MojoPlatform_isfile(fullpath)) { - ar->prevEnum.filesize = statbuf.st_size; + ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE; + ar->prevEnum.filesize = MojoPlatform_filesize(fullpath); + } // if - // We currently force the perms from physical files, since CDs on - // Linux tend to mark every files as executable and read-only. If you - // want to install something with specific permissions, wrap it in a - // tarball, or use Setup.File.permissions, or return a permissions - // string from Setup.File.filter. - //ar->prevEnum.perms = statbuf.st_mode; - ar->prevEnum.perms = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - if (S_ISREG(statbuf.st_mode)) - ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE; - - else if (S_ISLNK(statbuf.st_mode)) + else if (MojoPlatform_issymlink(fullpath)) + { + ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK; + ar->prevEnum.linkdest = MojoPlatform_readlink(fullpath); + if (ar->prevEnum.linkdest == NULL) { - ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK; - ar->prevEnum.linkdest = MojoPlatform_readlink(fullpath); - if (ar->prevEnum.linkdest == NULL) - { - free(fullpath); - return MojoArchive_dir_enumNext(ar); - } // if - } // else if + free(fullpath); + return MojoArchive_dir_enumNext(ar); + } // if + } // else if - else if (S_ISDIR(statbuf.st_mode)) + else if (MojoPlatform_isdir(fullpath)) + { + void *dir = MojoPlatform_opendir(fullpath); + ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR; + if (dir == NULL) { - void *dir = MojoPlatform_opendir(fullpath); - ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR; - if (dir == NULL) - { - free(fullpath); - return MojoArchive_dir_enumNext(ar); - } // if - // push this dir on the stack. Next enum will start there. - pushDirStack(&inst->dirs, fullpath, dir); - } // else if + free(fullpath); + return MojoArchive_dir_enumNext(ar); + } // if + + // push this dir on the stack. Next enum will start there. + pushDirStack(&inst->dirs, fullpath, dir); + } // else if + + else + { + assert(false && "possible file i/o error?"); } // else free(fullpath); @@ -475,11 +459,16 @@ MojoArchive *ar = NULL; MojoArchiveDirInstance *inst; char *real = MojoPlatform_realpath(dirname); - struct stat st; - if ( (real == NULL) || (stat(real, &st) == -1) || (!S_ISDIR(st.st_mode)) ) + if (real == NULL) return NULL; + if (!MojoPlatform_exists(real, NULL)) + return NULL; + + if (!MojoPlatform_isdir(real)) + return NULL; + inst = (MojoArchiveDirInstance *) xmalloc(sizeof (MojoArchiveDirInstance)); inst->base = real; ar = (MojoArchive *) xmalloc(sizeof (MojoArchive)); @@ -508,17 +497,23 @@ if ((cmd = cmdlinestr("base", "MOJOSETUP_BASE", NULL)) != NULL) { - if (MojoPlatform_isdir(cmd)) - GBaseArchive = MojoArchive_newFromDirectory(cmd); - else + char *real = MojoPlatform_realpath(cmd); + if (real != NULL) { - io = MojoInput_newFromFile(cmd); - if (io != NULL) - GBaseArchive = MojoArchive_newFromInput(io, cmd); - } // else + if (MojoPlatform_isdir(real)) + GBaseArchive = MojoArchive_newFromDirectory(real); + else + { + io = MojoInput_newFromFile(real); + if (io != NULL) + GBaseArchive = MojoArchive_newFromInput(io, real); + } // else - if (GBaseArchive != NULL) - basepath = xstrdup(cmd); + if (GBaseArchive != NULL) + basepath = real; + else + free(real); + } // if } // else if else Modified: trunk/lua_glue.c =================================================================== --- trunk/lua_glue.c 2007-09-20 06:57:04 UTC (rev 339) +++ trunk/lua_glue.c 2007-09-20 08:34:55 UTC (rev 340) @@ -876,9 +876,23 @@ { const char *dir = luaL_checkstring(L, 1); return retvalBoolean(L, MojoPlatform_isdir(dir)); -} // luahook_platform_writable +} // luahook_platform_isdir +static int luahook_platform_issymlink(lua_State *L) +{ + const char *fname = luaL_checkstring(L, 1); + return retvalBoolean(L, MojoPlatform_issymlink(fname)); +} // luahook_platform_issymlink + + +static int luahook_platform_isfile(lua_State *L) +{ + const char *fname = luaL_checkstring(L, 1); + return retvalBoolean(L, MojoPlatform_isfile(fname)); +} // luahook_platform_isfile + + static int luahook_platform_symlink(lua_State *L) { const char *src = luaL_checkstring(L, 1); @@ -1458,6 +1472,8 @@ set_cfunc(luaState, luahook_platform_exists, "exists"); set_cfunc(luaState, luahook_platform_writable, "writable"); set_cfunc(luaState, luahook_platform_isdir, "isdir"); + set_cfunc(luaState, luahook_platform_issymlink, "issymlink"); + set_cfunc(luaState, luahook_platform_isfile, "isfile"); set_cfunc(luaState, luahook_platform_symlink, "symlink"); set_cfunc(luaState, luahook_platform_mkdir, "mkdir"); lua_setfield(luaState, -2, "platform"); Modified: trunk/mojosetup.c =================================================================== --- trunk/mojosetup.c 2007-09-20 06:57:04 UTC (rev 339) +++ trunk/mojosetup.c 2007-09-20 08:34:55 UTC (rev 340) @@ -316,7 +316,7 @@ #define DEFLOGLEV "everything" #endif MojoSetupLogLevel MojoLog_logLevel = MOJOSETUP_LOG_EVERYTHING; -static FILE *logFile = NULL; +static void *logFile = NULL; void MojoLog_initLogging(void) { @@ -336,16 +336,23 @@ else // Unknown string gets everything...that'll teach you. MojoLog_logLevel = MOJOSETUP_LOG_EVERYTHING; + // !!! FIXME: allow logging to stdout on Unix. if (fname != NULL) - logFile = fopen(fname, "w"); + { + const uint32 flags = MOJOFILE_WRITE|MOJOFILE_CREATE|MOJOFILE_TRUNCATE; + const uint16 mode = MojoPlatform_defaultFilePerms(); + logFile = MojoPlatform_open(fname, flags, mode); + } // if } // MojoLog_initLogging void MojoLog_deinitLogging(void) { if (logFile != NULL) - fclose(logFile); - logFile = NULL; + { + MojoPlatform_close(logFile); + logFile = NULL; + } // if } // MojoLog_deinitLogging @@ -364,9 +371,10 @@ MojoPlatform_log(buf); if (logFile != NULL) { - fputs(buf, logFile); - fputs("\n", logFile); - fflush(logFile); + const char *endl = MOJOPLATFORM_ENDLINE; + MojoPlatform_write(logFile, buf, strlen(buf)); + MojoPlatform_write(logFile, endl, strlen(endl)); + MojoPlatform_flush(logFile); } // if } // if } // addLog Modified: trunk/platform.h =================================================================== --- trunk/platform.h 2007-09-20 06:57:04 UTC (rev 339) +++ trunk/platform.h 2007-09-20 08:34:55 UTC (rev 340) @@ -73,6 +73,15 @@ boolean MojoPlatform_isdir(const char *dir); // !!! FIXME: comment me. +boolean MojoPlatform_issymlink(const char *fname); + +// !!! FIXME: comment me. +boolean MojoPlatform_isfile(const char *fname); + +// !!! FIXME: comment me. +int64 MojoPlatform_filesize(const char *fname); + +// !!! FIXME: comment me. boolean MojoPlatform_perms(const char *fname, uint16 *p); // !!! FIXME: comment me. @@ -81,6 +90,42 @@ // !!! FIXME: comment me. char *MojoPlatform_findMedia(const char *uniquefile); +// Flag values for MojoPlatform_fopen(). +typedef enum +{ + MOJOFILE_READ=(1<<0), + MOJOFILE_WRITE=(1<<1), + MOJOFILE_CREATE=(1<<2), + MOJOFILE_EXCLUSIVE=(1<<3), + MOJOFILE_TRUNCATE=(1<<4), + MOJOFILE_APPEND=(1<<5), +} MojoFileFlags; + +typedef enum +{ + MOJOSEEK_SET, + MOJOSEEK_CURRENT, + MOJOSEEK_END +} MojoFileSeek; + +// !!! FIXME: comment me. +void *MojoPlatform_open(const char *fname, uint32 flags, uint16 mode); +// !!! FIXME: comment me. +int64 MojoPlatform_read(void *fd, void *buf, uint32 bytes); +// !!! FIXME: comment me. +int64 MojoPlatform_write(void *fd, const void *buf, uint32 bytes); +// !!! FIXME: comment me. +int64 MojoPlatform_tell(void *fd); +// !!! FIXME: comment me. +int64 MojoPlatform_seek(void *fd, int64 offset, MojoFileSeek whence); +// !!! FIXME: comment me. +int64 MojoPlatform_flen(void *fd); +// !!! FIXME: comment me. +boolean MojoPlatform_flush(void *fd); +// !!! FIXME: comment me. +boolean MojoPlatform_close(void *fd); + + // Enumerate a directory. Returns an opaque pointer that can be used with // repeated calls to MojoPlatform_readdir() to enumerate the names of // directory entries. Returns NULL on error. Non-NULL values should be passed @@ -100,7 +145,7 @@ void MojoPlatform_closedir(void *dirhandle); // Convert a string into a permissions bitmask. On Unix, this is currently -// expected to be an octal string like "0755", but may except other forms +// expected to be an octal string like "0755", but may expect other forms // in the future, and other platforms may need to interpret permissions // differently. (str) may be NULL for defaults, and is considered valid. // If (str) is not valid, return a reasonable default and set (*valid) to @@ -175,6 +220,13 @@ #error Unknown processor architecture. #endif +// Other basic truths... +#if PLATFORM_WINDOWS +#define MOJOPLATFORM_ENDLINE "\r\n" +#else +#define MOJOPLATFORM_ENDLINE "\n" +#endif + #ifdef __cplusplus } #endif Modified: trunk/platform_unix.c =================================================================== --- trunk/platform_unix.c 2007-09-20 06:57:04 UTC (rev 339) +++ trunk/platform_unix.c 2007-09-20 08:34:55 UTC (rev 340) @@ -541,7 +541,7 @@ { boolean retval = false; struct stat statbuf; - if (stat(dir, &statbuf) != -1) + if (lstat(dir, &statbuf) != -1) { if (S_ISDIR(statbuf.st_mode)) retval = true; @@ -550,6 +550,125 @@ } // MojoPlatform_isdir +boolean MojoPlatform_issymlink(const char *dir) +{ + boolean retval = false; + struct stat statbuf; + if (lstat(dir, &statbuf) != -1) + { + if (S_ISLNK(statbuf.st_mode)) + retval = true; + } // if + return retval; +} // MojoPlatform_issymlink + + +boolean MojoPlatform_isfile(const char *dir) +{ + boolean retval = false; + struct stat statbuf; + if (lstat(dir, &statbuf) != -1) + { + if (S_ISREG(statbuf.st_mode)) + retval = true; + } // if + return retval; +} // MojoPlatform_issymlink + + +void *MojoPlatform_open(const char *fname, uint32 flags, uint16 mode) +{ + void *retval = NULL; + int fd = -1; + int unixflags = 0; + + if ((flags & MOJOFILE_READ) && (flags & MOJOFILE_WRITE)) + unixflags |= O_RDWR; + else if (flags & MOJOFILE_READ) + unixflags |= O_RDONLY; + else if (flags & MOJOFILE_WRITE) + unixflags |= O_WRONLY; + else + return NULL; // have to specify SOMETHING. + + if (flags & MOJOFILE_APPEND) + unixflags |= O_APPEND; + if (flags & MOJOFILE_TRUNCATE) + unixflags |= O_TRUNC; + if (flags & MOJOFILE_CREATE) + unixflags |= O_CREAT; + if (flags & MOJOFILE_EXCLUSIVE) + unixflags |= O_EXCL; + + fd = open(fname, unixflags, (mode_t) mode); + if (fd != -1) + { + int *intptr = (int *) xmalloc(sizeof (int)); + *intptr = fd; + retval = intptr; + } // if + + return retval; +} // MojoPlatform_open + + +int64 MojoPlatform_read(void *fd, void *buf, uint32 bytes) +{ + return (int64) read(*((int *) fd), buf, bytes); +} // MojoPlatform_read + + +int64 MojoPlatform_write(void *fd, const void *buf, uint32 bytes) +{ + return (int64) write(*((int *) fd), buf, bytes); +} // MojoPlatform_write + + +int64 MojoPlatform_tell(void *fd) +{ + return (int64) lseek(*((int *) fd), 0, SEEK_CUR); +} // MojoPlatform_tell + + +int64 MojoPlatform_seek(void *fd, int64 offset, MojoFileSeek whence) +{ + int unixwhence; + switch (whence) + { + case MOJOSEEK_SET: unixwhence = SEEK_SET; break; + case MOJOSEEK_CURRENT: unixwhence = SEEK_CUR; break; + case MOJOSEEK_END: unixwhence = SEEK_END; break; + default: return -1; // !!! FIXME: maybe just abort? + } // switch + + return (int64) lseek(*((int *) fd), offset, unixwhence); +} // MojoPlatform_seek + + +int64 MojoPlatform_flen(void *fd) +{ + struct stat statbuf; + if (fstat(*((int *) fd), &statbuf) == -1) + return -1; + return((int64) statbuf.st_size); +} // MojoPlatform_flen + + +boolean MojoPlatform_flush(void *fd) +{ + return (fsync(*((int *) fd)) == 0); +} // MojoPlatform_flush + + +boolean MojoPlatform_close(void *fd) +{ + boolean retval = false; + if (close(*((int *) fd)) == 0) + free(fd); + return retval; +} // MojoPlatform_close + + void *MojoPlatform_opendir(const char *dirname) { return opendir(dirname); @@ -583,6 +702,16 @@ } // MojoPlatform_closedir +int64 MojoPlatform_filesize(const char *fname) +{ + int retval = -1; + struct stat statbuf; + if (stat(fname, &statbuf) != -1) + retval = (int64) statbuf.st_size; + return retval; +} // MojoPlatform_filesize + + boolean MojoPlatform_perms(const char *fname, uint16 *p) { boolean retval = false; From DONOTREPLY at icculus.org Thu Sep 20 04:44:55 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 04:44:55 -0400 Subject: r341 - trunk/libfetch Message-ID: <20070920084455.6613.qmail@icculus.org> Author: icculus Date: 2007-09-20 04:44:55 -0400 (Thu, 20 Sep 2007) New Revision: 341 Modified: trunk/libfetch/README.txt Log: Updated libfetch README a little. Modified: trunk/libfetch/README.txt =================================================================== --- trunk/libfetch/README.txt 2007-09-20 08:34:55 UTC (rev 340) +++ trunk/libfetch/README.txt 2007-09-20 08:44:55 UTC (rev 341) @@ -9,7 +9,10 @@ This just has minor modifications to make it play nicely with our build system, and code, and stuff we don't need was trimmed out. +Changes made for MojoSetup that aren't part of a virgin copy of libfetch are + noted with "#if __MOJOSETUP__" sections. + Here is the libfetch copyright from common.c ... /*- From DONOTREPLY at icculus.org Thu Sep 20 15:27:00 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 20 Sep 2007 15:27:00 -0400 Subject: r342 - trunk Message-ID: <20070920192700.18972.qmail@icculus.org> Author: icculus Date: 2007-09-20 15:27:00 -0400 (Thu, 20 Sep 2007) New Revision: 342 Modified: trunk/platform_unix.c Log: Patched to compile on Linux. Modified: trunk/platform_unix.c =================================================================== --- trunk/platform_unix.c 2007-09-20 08:44:55 UTC (rev 341) +++ trunk/platform_unix.c 2007-09-20 19:27:00 UTC (rev 342) @@ -25,6 +25,7 @@ #include #include #include +#include #if MOJOSETUP_HAVE_SYS_UCRED_H # ifdef MOJOSETUP_HAVE_MNTENT_H From DONOTREPLY at icculus.org Sun Sep 23 02:23:08 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 23 Sep 2007 02:23:08 -0400 Subject: r343 - trunk Message-ID: <20070923062308.7649.qmail@icculus.org> Author: icculus Date: 2007-09-23 02:23:08 -0400 (Sun, 23 Sep 2007) New Revision: 343 Modified: trunk/fileio.c Log: Removed a STUBBED that doesn't apply anymore. Modified: trunk/fileio.c =================================================================== --- trunk/fileio.c 2007-09-20 19:27:00 UTC (rev 342) +++ trunk/fileio.c 2007-09-23 06:23:08 UTC (rev 343) @@ -114,8 +114,6 @@ flen = in->length(in); - STUBBED("fopen?"); - MojoPlatform_unlink(fname); if (!iofailure) { From DONOTREPLY at icculus.org Sun Sep 23 02:33:02 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 23 Sep 2007 02:33:02 -0400 Subject: r344 - trunk Message-ID: <20070923063302.12553.qmail@icculus.org> Author: icculus Date: 2007-09-23 02:33:02 -0400 (Sun, 23 Sep 2007) New Revision: 344 Modified: trunk/universal.h Log: Removed stdio from STUBBED macro. Modified: trunk/universal.h =================================================================== --- trunk/universal.h 2007-09-23 06:23:08 UTC (rev 343) +++ trunk/universal.h 2007-09-23 06:33:02 UTC (rev 344) @@ -317,7 +317,7 @@ if (!seen_this) \ { \ seen_this = true; \ - fprintf(stderr, "STUBBED: %s at %s (%s:%d)\n", x, __FUNCTION__, \ + logDebug("STUBBED: %s at %s (%s:%d)\n", x, __FUNCTION__, \ __FILE__, __LINE__); \ } \ } while (false) From DONOTREPLY at icculus.org Mon Sep 24 22:24:10 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 24 Sep 2007 22:24:10 -0400 Subject: r345 - trunk Message-ID: <20070925022410.11185.qmail@icculus.org> Author: icculus Date: 2007-09-24 22:24:10 -0400 (Mon, 24 Sep 2007) New Revision: 345 Modified: trunk/platform_unix.c Log: MojoPlatform_filesize() should only be used on regular files and not follow symlinks. Modified: trunk/platform_unix.c =================================================================== --- trunk/platform_unix.c 2007-09-23 06:33:02 UTC (rev 344) +++ trunk/platform_unix.c 2007-09-25 02:24:10 UTC (rev 345) @@ -707,7 +707,7 @@ { int retval = -1; struct stat statbuf; - if (stat(fname, &statbuf) != -1) + if ( (lstat(fname, &statbuf) != -1) && (S_ISREG(statbuf.st_mode)) ) retval = (int64) statbuf.st_size; return retval; } // MojoPlatform_filesize From DONOTREPLY at icculus.org Mon Sep 24 22:24:31 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 24 Sep 2007 22:24:31 -0400 Subject: r346 - trunk Message-ID: <20070925022431.11382.qmail@icculus.org> Author: icculus Date: 2007-09-24 22:24:31 -0400 (Mon, 24 Sep 2007) New Revision: 346 Modified: trunk/platform.h Log: Documented some of the platform layer interfaces. Modified: trunk/platform.h =================================================================== --- trunk/platform.h 2007-09-25 02:24:10 UTC (rev 345) +++ trunk/platform.h 2007-09-25 02:24:31 UTC (rev 346) @@ -54,7 +54,10 @@ // on failure. The caller is responsible for freeing the returned pointer! char *MojoPlatform_readlink(const char *linkname); -// !!! FIXME: comment me. +// !!! FIXME: we really can't do this in a 16-bit value...non-Unix platforms +// !!! FIXME: and Extended Attributes need more. +// Create a directory in the physical filesystem, with (perms) permissions. +// returns true if directory is created, false otherwise. boolean MojoPlatform_mkdir(const char *path, uint16 perms); // Move a file to a new name. This has to be a fast (if not atomic) operation, @@ -63,31 +66,55 @@ // Returns true on successful rename, false otherwise. boolean MojoPlatform_rename(const char *src, const char *dst); -// !!! FIXME: comment me. +// Determine if dir/fname exists in the native filesystem. It doesn't matter +// if it's a directory, file, symlink, etc, we're just looking for the +// existance of the entry itself. (fname) may be NULL, in which case, +// (dir) contains the whole path, otherwise, the platform layer needs to +// build the path: (on Unix: dir/path, on Windows: dir\\path, etc). +// This is a convenience thing for the caller. +// Returns true if path in question exists, false otherwise. boolean MojoPlatform_exists(const char *dir, const char *fname); -// !!! FIXME: comment me. +// Returns true if (fname) in the native filesystem is writable. If (fname) +// is a directory, this means that the contents of the directory can be +// added to (create files, delete files, etc). If (fname) is a file, this +// means that this process has write access to the file. +// Returns false if (fname) isn't writable. boolean MojoPlatform_writable(const char *fname); -// !!! FIXME: comment me. +// Returns true if (dir) is a directory in the physical filesystem, false +// otherwise (including if (dir) doesn't exist). Don't follow symlinks. boolean MojoPlatform_isdir(const char *dir); -// !!! FIXME: comment me. +// Returns true if (fname) is a symlink in the physical filesystem, false +// otherwise (including if (fname) doesn't exist). Don't follow symlinks. boolean MojoPlatform_issymlink(const char *fname); -// !!! FIXME: comment me. +// Returns true if (fname) is a regular file in the physical filesystem, false +// otherwise (including if (fname) doesn't exist). Don't follow symlinks. boolean MojoPlatform_isfile(const char *fname); -// !!! FIXME: comment me. +// Returns size, in bytes, of the file (fname) in the physical filesystem. +// Return -1 if file is missing or not a file. Don't follow symlinks. int64 MojoPlatform_filesize(const char *fname); +// !!! FIXME: we really can't do this in a 16-bit value...non-Unix platforms +// !!! FIXME: and Extended Attributes need more. // !!! FIXME: comment me. boolean MojoPlatform_perms(const char *fname, uint16 *p); +// !!! FIXME: we really can't do this in a 16-bit value...non-Unix platforms +// !!! FIXME: and Extended Attributes need more. // !!! FIXME: comment me. boolean MojoPlatform_chmod(const char *fname, uint16 p); -// !!! FIXME: comment me. +// Try to locate a specific piece of media (usually an inserted CD or DVD). +// (uniquefile) is a path that should exist on the media; its presence +// should uniquely identify the media. +// Returns the path of the media's mount point in the physical filesystem +// (something like "E:\\" on Windows or "/mnt/cdrom" on Unix), or NULL if +// the media isn't found (needed disc isn't inserted, etc). +// Caller must free return value! char *MojoPlatform_findMedia(const char *uniquefile); // Flag values for MojoPlatform_fopen(). @@ -108,24 +135,45 @@ MOJOSEEK_END } MojoFileSeek; -// !!! FIXME: comment me. +// !!! FIXME: we really can't do this in a 16-bit value...non-Unix platforms +// !!! FIXME: and Extended Attributes need more. +// Open file (fname). This wraps a subset of the Unix open() syscall. Use +// MojoFileFlags for (flags). If creating a file, use (mode) for the new +// file's permissions. +// Returns an opaque handle on success, NULL on error. Caller must free +// handle with MojoPlatform_close() when done with it. void *MojoPlatform_open(const char *fname, uint32 flags, uint16 mode); -// !!! FIXME: comment me. + +// Read (bytes) bytes from (fd) into (buf). This wraps the Unix read() syscall. +// Returns number of bytes read, -1 on error. int64 MojoPlatform_read(void *fd, void *buf, uint32 bytes); -// !!! FIXME: comment me. + +// Write (bytes) bytes from (buf) into (fd). This wraps the Unix write() +// syscall. Returns number of bytes read, -1 on error. int64 MojoPlatform_write(void *fd, const void *buf, uint32 bytes); -// !!! FIXME: comment me. + +// Reports byte offset of file pointer in (fd), or -1 on error. int64 MojoPlatform_tell(void *fd); -// !!! FIXME: comment me. + +// Seek to (offset) byte offset of file pointer in (fd), relative to (whence). +// This wraps the Unix lseek() syscall. Returns byte offset from the start +// of the file, -1 on error. int64 MojoPlatform_seek(void *fd, int64 offset, MojoFileSeek whence); -// !!! FIXME: comment me. + +// Get the size, in bytes, of a file, referenced by its opaque handle. +// (This pulls the data through an fstat() on Unix.) Retuns -1 on error. int64 MojoPlatform_flen(void *fd); -// !!! FIXME: comment me. + +// Force any pending data to disk, returns true on success, false if there +// was an i/o error. boolean MojoPlatform_flush(void *fd); -// !!! FIXME: comment me. + +// Free any resources associated with (fd), flushing any pending data to disk, +// and closing the file. (fd) becomes invalid after this call returns +// successfully. This wraps the Unix close() syscall. Returns true on +// success, false on i/o error. boolean MojoPlatform_close(void *fd); - // Enumerate a directory. Returns an opaque pointer that can be used with // repeated calls to MojoPlatform_readdir() to enumerate the names of // directory entries. Returns NULL on error. Non-NULL values should be passed From DONOTREPLY at icculus.org Tue Sep 25 04:46:09 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 25 Sep 2007 04:46:09 -0400 Subject: r347 - trunk Message-ID: <20070925084609.10990.qmail@icculus.org> Author: icculus Date: 2007-09-25 04:46:09 -0400 (Tue, 25 Sep 2007) New Revision: 347 Modified: trunk/CMakeLists.txt Log: Turn off compiler whining on VS.NET 2005. Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-25 02:24:31 UTC (rev 346) +++ trunk/CMakeLists.txt 2007-09-25 08:46:09 UTC (rev 347) @@ -42,6 +42,7 @@ IF(WINDOWS) ADD_DEFINITIONS(-DPLATFORM_WINDOWS=1) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1) ENDIF(WINDOWS) IF(MACOSX) From DONOTREPLY at icculus.org Tue Sep 25 05:19:37 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 25 Sep 2007 05:19:37 -0400 Subject: r348 - trunk Message-ID: <20070925091937.27521.qmail@icculus.org> Author: icculus Date: 2007-09-25 05:19:37 -0400 (Tue, 25 Sep 2007) New Revision: 348 Modified: trunk/universal.h Log: MSVC doesn't support the "inline" keyword directly, outside C++. Modified: trunk/universal.h =================================================================== --- trunk/universal.h 2007-09-25 08:46:09 UTC (rev 347) +++ trunk/universal.h 2007-09-25 09:19:37 UTC (rev 348) @@ -48,6 +48,11 @@ #define true 1 #define false 0 +// MSVC doesn't support the "inline" keyword for normal C sources, just C++. +#if defined(_MSC_VER) && !defined(__cplusplus) && !defined(inline) +#define inline __inline +#endif + // Compiler-enforced printf() safety helper. // This is appended to function declarations that use printf-style semantics, // and will make sure your passed the right params to "..." for the From DONOTREPLY at icculus.org Tue Sep 25 05:23:44 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 25 Sep 2007 05:23:44 -0400 Subject: r349 - trunk Message-ID: <20070925092344.29523.qmail@icculus.org> Author: icculus Date: 2007-09-25 05:23:44 -0400 (Tue, 25 Sep 2007) New Revision: 349 Modified: trunk/gui_www.c Log: Prevent conflicts between the system headers and universal.h on Windows by trimming the massive dependencies that winsock.h -> windows.h pulls in by default. Modified: trunk/gui_www.c =================================================================== --- trunk/gui_www.c 2007-09-25 09:19:37 UTC (rev 348) +++ trunk/gui_www.c 2007-09-25 09:23:44 UTC (rev 349) @@ -19,16 +19,13 @@ CREATE_MOJOGUI_ENTRY_POINT(www) #endif -#include -#include -#include #include #define FREE_AND_NULL(x) { free(x); x = NULL; } - // tapdance between things WinSock and BSD Sockets define differently... #if PLATFORM_WINDOWS + #define WIN32_LEAN_AND_MEAN #include typedef int socklen_t; From DONOTREPLY at icculus.org Tue Sep 25 05:51:03 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 25 Sep 2007 05:51:03 -0400 Subject: r350 - trunk Message-ID: <20070925095103.8938.qmail@icculus.org> Author: icculus Date: 2007-09-25 05:51:03 -0400 (Tue, 25 Sep 2007) New Revision: 350 Modified: trunk/archive_tar.c trunk/archive_zip.c trunk/buildver.c trunk/checksum_crc32.c trunk/gui_www.c trunk/lua_glue.c trunk/universal.h Log: Patched to compile (but not link!) on Windows with VS.NET 2005. libfetch isn't ported, everything else builds. Modified: trunk/archive_tar.c =================================================================== --- trunk/archive_tar.c 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/archive_tar.c 2007-09-25 09:51:03 UTC (rev 350) @@ -129,7 +129,7 @@ if (br > GZIP_READBUFSIZE) br = GZIP_READBUFSIZE; - br = origio->read(origio, info->buffer, br); + br = origio->read(origio, info->buffer, (uint32) br); if (br <= 0) return -1; @@ -338,7 +338,7 @@ if (br > BZIP2_READBUFSIZE) br = BZIP2_READBUFSIZE; - br = origio->read(origio, info->buffer, br); + br = origio->read(origio, info->buffer, (uint32) br); if (br <= 0) return -1; @@ -444,7 +444,7 @@ TARinput *input = (TARinput *) io->opaque; int64 pos = io->tell(io); if ((pos + bufsize) > input->fsize) - bufsize = input->fsize - pos; + bufsize = (uint32) (input->fsize - pos); return input->ar->io->read(input->ar->io, buf, bufsize); } // MojoInput_tar_read @@ -452,7 +452,7 @@ { TARinput *input = (TARinput *) io->opaque; boolean retval = false; - if (pos < input->fsize) + if (pos < ((uint64) input->fsize)) retval = input->ar->io->seek(input->ar->io, input->offset + pos); return retval; } // MojoInput_tar_seek Modified: trunk/archive_zip.c =================================================================== --- trunk/archive_zip.c 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/archive_zip.c 2007-09-25 09:51:03 UTC (rev 350) @@ -79,8 +79,8 @@ PHYSFS_uint32 size, PHYSFS_uint32 count) { MojoInput *io = (MojoInput *) opaque; - uint32 rc = io->read(io, buffer, size * count); - return rc / size; + int64 rc = io->read(io, buffer, size * count); + return rc / size; // !!! FIXME: what if rc == -1? } static int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos) Modified: trunk/buildver.c =================================================================== --- trunk/buildver.c 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/buildver.c 2007-09-25 09:51:03 UTC (rev 350) @@ -28,15 +28,15 @@ #endif #ifndef __VERSION__ -#define __VERSION__ (Unknown compiler version) +#define __VERSION__ "(Unknown compiler version)" #endif #ifndef __DATE__ -#define __DATE__ (Unknown build date) +#define __DATE__ "(Unknown build date)" #endif #ifndef __TIME__ -#define __TIME__ (Unknown build time) +#define __TIME__ "(Unknown build time)" #endif #ifndef COMPILER Modified: trunk/checksum_crc32.c =================================================================== --- trunk/checksum_crc32.c 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/checksum_crc32.c 2007-09-25 09:51:03 UTC (rev 350) @@ -12,7 +12,7 @@ { uint32 crc = (uint32) *_crc; - int n; + uint32 n; for (n = 0; n < len; n++) { uint32 xorval = (uint32) ((crc ^ buf[n]) & 0xFF); Modified: trunk/gui_www.c =================================================================== --- trunk/gui_www.c 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/gui_www.c 2007-09-25 09:51:03 UTC (rev 350) @@ -25,11 +25,11 @@ // tapdance between things WinSock and BSD Sockets define differently... #if PLATFORM_WINDOWS - #define WIN32_LEAN_AND_MEAN #include typedef int socklen_t; + #define setprotoent(x) assert(x == 0) #define sockErrno() WSAGetLastError() #define wouldBlockError(err) (err == WSAEWOULDBLOCK) #define intrError(err) (err == WSAEINTR) @@ -204,7 +204,7 @@ static int strAdd(char **ptr, size_t *len, size_t *alloc, const char *fmt, ...) { - int bw = 0; + size_t bw = 0; size_t avail = *alloc - *len; va_list ap; va_start(ap, fmt); @@ -567,7 +567,7 @@ #if ((!defined _NDEBUG) && (!defined NDEBUG)) { int on = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)); + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &on, sizeof (on)); } #endif @@ -978,7 +978,14 @@ char *htmltext = NULL; char *text = NULL; size_t len = 0, alloc = 0; + int i, rc; + const char *buttons[] = { "cancel", "ok" }; + const char *locButtons[] = { + htmlescape(entry->_("Cancel")), + htmlescape(entry->_("OK")), + }; + // !!! FIXME: better text. char *title = entry->xstrdup(entry->_("Media change")); // !!! FIXME: better text. @@ -987,12 +994,6 @@ htmltext = htmlescape(text); free(text); - int i, rc; - const char *buttons[] = { "cancel", "ok" }; - const char *locButtons[] = { - htmlescape(entry->_("Cancel")), - htmlescape(entry->_("OK")), - }; assert(STATICARRAYLEN(buttons) == STATICARRAYLEN(locButtons)); rc = doPromptPage(title, htmltext, true, "insertmedia", buttons, Modified: trunk/lua_glue.c =================================================================== --- trunk/lua_glue.c 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/lua_glue.c 2007-09-25 09:51:03 UTC (rev 350) @@ -834,7 +834,7 @@ lua_newtable(L); set_string(L, entinfo->filename, "filename"); set_string(L, entinfo->linkdest, "linkdest"); - set_number(L, entinfo->filesize, "filesize"); + set_number(L, (lua_Number) entinfo->filesize, "filesize"); set_string(L, typestr, "type"); } // else @@ -1257,7 +1257,7 @@ if (lua_istable(L, 1)) { - int i; + size_t i; reccount = lua_objlen(L, 1); recommend = (char **) alloca(reccount * sizeof (char *)); Modified: trunk/universal.h =================================================================== --- trunk/universal.h 2007-09-25 09:23:44 UTC (rev 349) +++ trunk/universal.h 2007-09-25 09:51:03 UTC (rev 350) @@ -20,6 +20,19 @@ #include #include // !!! FIXME: maybe use this in platform layer? +// Windows system headers conflict with MojoSetup typedefs, so chop out +// all the massive and unnecessary dependencies that windows.h pulls in... +#if PLATFORM_WINDOWS +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#if _MSC_VER +#include // need this to get alloca() in MSVC. +// !!! FIXME: temporary solution. +#define snprintf _snprintf +#define strcasecmp(x,y) _stricmp(x,y) +#endif + #ifdef __cplusplus extern "C" { #endif From DONOTREPLY at icculus.org Tue Sep 25 06:29:04 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 25 Sep 2007 06:29:04 -0400 Subject: r351 - trunk Message-ID: <20070925102904.27093.qmail@icculus.org> Author: icculus Date: 2007-09-25 06:29:03 -0400 (Tue, 25 Sep 2007) New Revision: 351 Modified: trunk/fileio.c trunk/gui.c trunk/mojosetup.c Log: Cleaned up some compiler warnings on VS.NET 2005. Modified: trunk/fileio.c =================================================================== --- trunk/fileio.c 2007-09-25 09:51:03 UTC (rev 350) +++ trunk/fileio.c 2007-09-25 10:29:03 UTC (rev 351) @@ -141,12 +141,12 @@ iofailure = true; else { - if (MojoPlatform_write(out, scratchbuf_128k, br) != br) + if (MojoPlatform_write(out, scratchbuf_128k, (uint32) br) != br) iofailure = true; else { if (checksums != NULL) - MojoChecksum_append(&sumctx, scratchbuf_128k, br); + MojoChecksum_append(&sumctx, scratchbuf_128k, (uint32) br); bw += br; } // else } // else Modified: trunk/gui.c =================================================================== --- trunk/gui.c 2007-09-25 09:51:03 UTC (rev 350) +++ trunk/gui.c 2007-09-25 10:29:03 UTC (rev 351) @@ -132,7 +132,7 @@ { const uint32 imglen = (uint32) io->length(io); uint8 *img = (uint8 *) xmalloc(imglen); - const uint32 br = io->read(io, img, imglen); + const uint32 br = (uint32) io->read(io, img, imglen); io->close(io); if (br == imglen) lib = MojoPlatform_dlopen(img, imglen); Modified: trunk/mojosetup.c =================================================================== --- trunk/mojosetup.c 2007-09-25 09:51:03 UTC (rev 350) +++ trunk/mojosetup.c 2007-09-25 10:29:03 UTC (rev 351) @@ -430,7 +430,7 @@ int fatal(const char *fmt, ...) { static boolean in_fatal = false; - size_t len = 128; + int len = 128; char *buf = NULL; int rc = 0; va_list ap; From DONOTREPLY at icculus.org Wed Sep 26 05:02:36 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 05:02:36 -0400 Subject: r352 - trunk Message-ID: <20070926090236.8568.qmail@icculus.org> Author: icculus Date: 2007-09-26 05:02:35 -0400 (Wed, 26 Sep 2007) New Revision: 352 Added: trunk/platform_windows.c Modified: trunk/platform_unix.c Log: First bulk of Windows platform layer. Probably doesn't even compile yet. Modified: trunk/platform_unix.c =================================================================== --- trunk/platform_unix.c 2007-09-25 10:29:03 UTC (rev 351) +++ trunk/platform_unix.c 2007-09-26 09:02:35 UTC (rev 352) @@ -574,7 +574,7 @@ retval = true; } // if return retval; -} // MojoPlatform_issymlink +} // MojoPlatform_isfile void *MojoPlatform_open(const char *fname, uint32 flags, uint16 mode) @@ -845,7 +845,7 @@ // /dev/shm may be able to avoid writing to physical media...try it first. const char *dirs[] = { "/dev/shm", getenv("TMPDIR"), P_tmpdir, "/tmp" }; - const char *tmpl = "mojosetup-gui-plugin-XXXXXX"; + const char *tmpl = "mojosetup-plugin-XXXXXX"; char fname[PATH_MAX]; void *retval = NULL; int i = 0; Added: trunk/platform_windows.c =================================================================== --- trunk/platform_windows.c (rev 0) +++ trunk/platform_windows.c 2007-09-26 09:02:35 UTC (rev 352) @@ -0,0 +1,1395 @@ +/** + * MojoSetup; a portable, flexible installation application. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +#if PLATFORM_WINDOWS + +#include "platform.h" +#include "gui.h" + +// Much of this file was lifted from PhysicsFS, http://icculus.org/physfs/ ... +// I wrote all this code under the same open source license, and own the +// copyright on it anyhow, so transferring it here is "safe". + +/* Forcibly disable UNICODE, since we manage this ourselves. */ +#ifdef UNICODE +#undef UNICODE +#endif + +#include + +// is Win95/Win98/WinME? (no Unicode, etc) +static boolean osIsWin9x = false; +static uint32 osMajorVer = 0; +static uint32 osMinorVer = 0; +static uint32 osBuildVer = 0; + +static uint32 startupTime = 0; + +// These allocation macros are much more complicated in PhysicsFS. +#define smallAlloc(x) xmalloc(x) +#define smallFree(x) xfree(x) + +// ...so is this. +#define BAIL_IF_MACRO(cond, err, ret) if (cond) return ret; +#define BAIL_MACRO(err, ret) return ret; + +#define LOWORDER_UINT64(pos) (PHYSFS_uint32) \ + (pos & 0x00000000FFFFFFFF) +#define HIGHORDER_UINT64(pos) (PHYSFS_uint32) \ + (((pos & 0xFFFFFFFF00000000) >> 32) & 0x00000000FFFFFFFF) + +/* + * 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 + +/* Not defined before the Vista SDK. */ +#ifndef IO_REPARSE_TAG_SYMLINK +#define IO_REPARSE_TAG_SYMLINK 0xA000000C +#endif + +#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \ + if (str == NULL) \ + w_assignto = NULL; \ + else { \ + const uint64 len = (uint64) ((strlen(str) * 4) + 1); \ + w_assignto = (WCHAR *) smallAlloc(len); \ + if (w_assignto != NULL) \ + utf8ToUcs2(str, (uint16 *) w_assignto, len); \ + } \ +} \ + +static uint64 wStrLen(const WCHAR *wstr) +{ + uint64 len = 0; + while (*(wstr++)) + len++; + return(len); +} // wStrLen + + +static char *unicodeToUtf8Heap(const WCHAR *w_str) +{ + char *retval = NULL; + if (w_str != NULL) + { + void *ptr = NULL; + const uint64 len = (wStrLen(w_str) * 4) + 1; + retval = (char *) xmalloc(len); + utf8FromUcs2((const uint16 *) w_str, retval, len); + retval = xrealloc(retval, strlen(retval) + 1); // shrink. + } // if + return(retval); +} // unicodeToUtf8Heap + + +static char *codepageToUtf8Heap(const char *cpstr) +{ + char *retval = NULL; + if (cpstr != NULL) + { + const int len = (int) (strlen(cpstr) + 1); + WCHAR *wbuf = (WCHAR *) smallAlloc(len * sizeof (WCHAR)); + BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, len, wbuf, len); + retval = (char *) xmalloc(len * 4); + utf8FromUcs2(wbuf, retval, len * 4); + smallFree(wbuf); + } /* if */ + return(retval); +} /* codepageToUtf8Heap */ + + +/* pointers for APIs that may not exist on some Windows versions... */ +static HANDLE libKernel32 = NULL; +static HANDLE libUserEnv = NULL; +static HANDLE libAdvApi32 = NULL; +static HANDLE libShell32 = NULL; +static DWORD (WINAPI *pGetModuleFileNameW)(HMODULE, LPWCH, DWORD); +static BOOL (WINAPI *pGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); +static BOOL (WINAPI *pGetUserNameW)(LPWSTR, LPDWORD); +static DWORD (WINAPI *pGetFileAttributesW)(LPCWSTR); +static HANDLE (WINAPI *pFindFirstFileW)(LPCWSTR, LPWIN32_FIND_DATAW); +static BOOL (WINAPI *pFindNextFileW)(HANDLE, LPWIN32_FIND_DATAW); +static DWORD (WINAPI *pGetCurrentDirectoryW)(DWORD, LPWSTR); +static BOOL (WINAPI *pDeleteFileW)(LPCWSTR); +static BOOL (WINAPI *pRemoveDirectoryW)(LPCWSTR); +static BOOL (WINAPI *pCreateDirectoryW)(LPCWSTR, LPSECURITY_ATTRIBUTES); +static BOOL (WINAPI *pGetFileAttributesExA) + (LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID); +static BOOL (WINAPI *pGetFileAttributesExW) + (LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID); +static DWORD (WINAPI *pFormatMessageW) + (DWORD, LPCVOID, DWORD, DWORD, LPWSTR, DWORD, va_list *); +static HANDLE (WINAPI *pCreateFileW) + (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPTSTR); +static BOOL (WINAPI *pMoveFileW)(LPCWSTR, LPCWSTR); +static void (WINAPI *pOutputDebugStringW)(LPCWSTR); + +/* + * Fallbacks for missing Unicode functions on Win95/98/ME. These are filled + * into the function pointers if looking up the real Unicode entry points + * in the system DLLs fails, so they're never used on WinNT/XP/Vista/etc. + * They make an earnest effort to convert to/from UTF-8 and UCS-2 to + * the user's current codepage. + */ + +static BOOL WINAPI fallbackGetUserNameW(LPWSTR buf, LPDWORD len) +{ + const DWORD cplen = *len; + char *cpstr = smallAlloc(cplen); + BOOL retval = GetUserNameA(cpstr, len); + if (buf != NULL) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, cplen, buf, *len); + smallFree(cpstr); + return(retval); +} /* fallbackGetUserNameW */ + +static DWORD WINAPI fallbackFormatMessageW(DWORD dwFlags, LPCVOID lpSource, + DWORD dwMessageId, DWORD dwLangId, + LPWSTR lpBuf, DWORD nSize, + va_list *Arguments) +{ + char *cpbuf = (char *) smallAlloc(nSize); + DWORD retval = FormatMessageA(dwFlags, lpSource, dwMessageId, dwLangId, + cpbuf, nSize, Arguments); + if (retval > 0) + MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize); + smallFree(cpbuf); + return(retval); +} /* fallbackFormatMessageW */ + +static DWORD WINAPI fallbackGetModuleFileNameW(HMODULE hMod, LPWCH lpBuf, + DWORD nSize) +{ + char *cpbuf = (char *) smallAlloc(nSize); + DWORD retval = GetModuleFileNameA(hMod, cpbuf, nSize); + if (retval > 0) + MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize); + smallFree(cpbuf); + return(retval); +} /* fallbackGetModuleFileNameW */ + +static DWORD WINAPI fallbackGetFileAttributesW(LPCWSTR fname) +{ + DWORD retval = 0; + const int buflen = (int) (wStrLen(fname) + 1); + char *cpstr = (char *) smallAlloc(buflen); + WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL); + retval = GetFileAttributesA(cpstr); + smallFree(cpstr); + return(retval); +} /* fallbackGetFileAttributesW */ + +static DWORD WINAPI fallbackGetCurrentDirectoryW(DWORD buflen, LPWSTR buf) +{ + DWORD retval = 0; + char *cpbuf = NULL; + if (buf != NULL) + cpbuf = (char *) smallAlloc(buflen); + retval = GetCurrentDirectoryA(buflen, cpbuf); + if (cpbuf != NULL) + { + MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,buf,buflen); + smallFree(cpbuf); + } /* if */ + return(retval); +} /* fallbackGetCurrentDirectoryW */ + +static BOOL WINAPI fallbackRemoveDirectoryW(LPCWSTR dname) +{ + BOOL retval = 0; + const int buflen = (int) (wStrLen(dname) + 1); + char *cpstr = (char *) smallAlloc(buflen); + WideCharToMultiByte(CP_ACP, 0, dname, buflen, cpstr, buflen, NULL, NULL); + retval = RemoveDirectoryA(cpstr); + smallFree(cpstr); + return(retval); +} /* fallbackRemoveDirectoryW */ + +static BOOL WINAPI fallbackCreateDirectoryW(LPCWSTR dname, + LPSECURITY_ATTRIBUTES attr) +{ + BOOL retval = 0; + const int buflen = (int) (wStrLen(dname) + 1); + char *cpstr = (char *) smallAlloc(buflen); + WideCharToMultiByte(CP_ACP, 0, dname, buflen, cpstr, buflen, NULL, NULL); + retval = CreateDirectoryA(cpstr, attr); + smallFree(cpstr); + return(retval); +} /* fallbackCreateDirectoryW */ + +static BOOL WINAPI fallbackDeleteFileW(LPCWSTR fname) +{ + BOOL retval = 0; + const int buflen = (int) (wStrLen(fname) + 1); + char *cpstr = (char *) smallAlloc(buflen); + WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL); + retval = DeleteFileA(cpstr); + smallFree(cpstr); + return(retval); +} /* fallbackDeleteFileW */ + +static HANDLE WINAPI fallbackCreateFileW(LPCWSTR fname, + DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttrs, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttrs, HANDLE hTemplFile) +{ + HANDLE retval; + const int buflen = (int) (wStrLen(fname) + 1); + char *cpstr = (char *) smallAlloc(buflen); + WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL); + retval = CreateFileA(cpstr, dwDesiredAccess, dwShareMode, lpSecurityAttrs, + dwCreationDisposition, dwFlagsAndAttrs, hTemplFile); + smallFree(cpstr); + return(retval); +} /* fallbackCreateFileW */ + +static BOOL WINAPI fallbackMoveFileW(LPCWSTR src, LPCWSTR dst) +{ + BOOL retval; + const int srcbuflen = (int) (wStrLen(src) + 1); + char *srccpstr = (char *) smallAlloc(srcbuflen); + const int dstbuflen = (int) (wStrLen(dst) + 1); + char *dstcpstr = (char *) smallAlloc(dstbuflen); + WideCharToMultiByte(CP_ACP,0,src,srcbuflen,srccpstr,srcbuflen,NULL,NULL); + WideCharToMultiByte(CP_ACP,0,dst,dstbuflen,dstcpstr,dstbuflen,NULL,NULL); + retval = MoveFileA(srccpstr, dstcpstr); + smallFree(srccpstr); + smallFree(dstcpstr); + return(retval); +} /* fallbackMoveFileW */ + +static void WINAPI fallbackOutputDebugStringW(LPCWSTR str) +{ + const int buflen = (int) (wStrLen(str) + 1); + char *cpstr = (char *) smallAlloc(buflen); + WideCharToMultiByte(CP_ACP, 0, str, buflen, cpstr, buflen, NULL, NULL); + retval = OutputDebugStringA(cpstr); + smallFree(cpstr); +} // fallbackOutputDebugStringW + + +/* A blatant abuse of pointer casting... */ +static int symLookup(HMODULE dll, void **addr, const char *sym) +{ + return( (*addr = GetProcAddress(dll, sym)) != NULL ); +} /* symLookup */ + + +static int findApiSymbols(void) +{ + const boolean osHasUnicode = !osIsWin9x; + HMODULE dll = NULL; + + #define LOOKUP_NOFALLBACK(x, reallyLook) { \ + if (reallyLook) \ + symLookup(dll, (void **) &p##x, #x); \ + else \ + p##x = NULL; \ + } + + #define LOOKUP(x, reallyLook) { \ + if ((!reallyLook) || (!symLookup(dll, (void **) &p##x, #x))) \ + p##x = fallback##x; \ + } + + /* Apparently Win9x HAS the Unicode entry points, they just don't WORK. */ + /* ...so don't look them up unless we're on NT+. (see osHasUnicode.) */ + + dll = libUserEnv = LoadLibraryA("userenv.dll"); + if (dll != NULL) + LOOKUP_NOFALLBACK(GetUserProfileDirectoryW, osHasUnicode); + + /* !!! FIXME: what do they call advapi32.dll on Win64? */ + dll = libAdvApi32 = LoadLibraryA("advapi32.dll"); + if (dll != NULL) + LOOKUP(GetUserNameW, osHasUnicode); + + /* !!! FIXME: what do they call kernel32.dll on Win64? */ + dll = libKernel32 = LoadLibraryA("kernel32.dll"); + if (dll != NULL) + { + LOOKUP_NOFALLBACK(GetFileAttributesExA, 1); + LOOKUP_NOFALLBACK(GetFileAttributesExW, osHasUnicode); + LOOKUP_NOFALLBACK(FindFirstFileW, osHasUnicode); + LOOKUP_NOFALLBACK(FindNextFileW, osHasUnicode); + LOOKUP(GetModuleFileNameW, osHasUnicode); + LOOKUP(FormatMessageW, osHasUnicode); + LOOKUP(GetFileAttributesW, osHasUnicode); + LOOKUP(GetCurrentDirectoryW, osHasUnicode); + LOOKUP(CreateDirectoryW, osHasUnicode); + LOOKUP(RemoveDirectoryW, osHasUnicode); + LOOKUP(CreateFileW, osHasUnicode); + LOOKUP(DeleteFileW, osHasUnicode); + LOOKUP(MoveFileW, osHasUnicode); + LOOKUP(OutputDebugStringW, osHasUnicode); + } /* if */ + + /* !!! FIXME: what do they call shell32.dll on Win64? */ + dll = libShell32 = LoadLibraryA("shell32.dll"); + if (dll != NULL) + LOOKUP_NOFALLBACK(SHGetFolderPathA, 1); + + #undef LOOKUP_NOFALLBACK + #undef LOOKUP + + return(1); +} /* findApiSymbols */ + + + +// ok, now the actual platform layer implementation... + +static struct timeval startup_time; + +char *MojoPlatform_currentWorkingDir(void) +{ + char *retval = NULL; + WCHAR *wbuf = NULL; + DWORD buflen = 0; + + buflen = pGetCurrentDirectoryW(buflen, NULL); + wbuf = (WCHAR *) smallAlloc((buflen + 2) * sizeof (WCHAR)); + BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL); + pGetCurrentDirectoryW(buflen, wbuf); + + if (wbuf[buflen - 2] == '\\') + wbuf[buflen - 1] = '\0'; /* just in case... */ + else + { + wbuf[buflen - 1] = '\\'; + wbuf[buflen] = '\0'; + } /* else */ + + retval = unicodeToUtf8Heap(wbuf); + smallFree(wbuf); + return(retval); +} // MojoPlatform_currentWorkingDir + + +char *MojoPlatform_readlink(const char *linkname) +{ + STUBBED("should use symlinks (reparse points) on Vista"); + return NULL; +} // MojoPlatform_readlink + + +// !!! FIXME: this code sort of sucks. +char *MojoPlatform_realpath(const char *path) +{ + // !!! FIXME: this should return NULL if (path) doesn't exist? + // !!! FIXME: Need to handle symlinks in Vista... + // !!! FIXME: try GetFullPathName() instead? + + // this function should be UTF-8 clean. + char *retval = NULL; + char *p = NULL; + + if ((path == NULL) || (*path == '\0')) + return NULL; + + retval = (char *) xmalloc(MAX_PATH); + + /* + * 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 = MojoPlatform_currentWorkingDir(); + if (currentDir == NULL) + { + free(retval); + return 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] = '\\'; + strcpy(retval + 3, path + 2); + } // else + } // else + } // if + + else // no drive letter specified. + { + if (path[0] == '\\') // absolute path. + { + retval[0] = currentDir[0]; + retval[1] = ':'; + strcpy(retval + 2, path); + } /* if */ + else + { + strcpy(retval, currentDir); + strcat(retval, path); + } // else + } // else + + free(currentDir); + } // else + + // (whew.) Ok, now take out "." and ".." path entries... + + p = retval; + while ( (p = strstr(p, "\\.")) != NULL) + { + // it's a "." entry that doesn't end the string. + if (p[2] == '\\') + memmove(p + 1, p + 3, strlen(p + 3) + 1); + + // it's a "." entry that ends the string. + else if (p[2] == '\0') + p[0] = '\0'; + + // it's a ".." entry. + else if (p[2] == '.') + { + char *prevEntry = p - 1; + while ((prevEntry != retval) && (*prevEntry != '\\')) + prevEntry--; + + if (prevEntry == retval) // make it look like a "." entry. + memmove(p + 1, p + 2, strlen(p + 2) + 1); + else + { + if (p[3] != '\0') // doesn't end string. + *prevEntry = '\0'; + else // ends string. + memmove(prevEntry + 1, p + 4, strlen(p + 4) + 1); + + p = prevEntry; + } // else + } // else if + + else + { + p++; // look past current char. + } // else + } // while + + // shrink the retval's memory block if possible... + return((char *) xrealloc(retval, strlen(retval) + 1)); +} // MojoPlatform_realpath + + +char *MojoPlatform_appBinaryPath(void) +{ + DWORD buflen = 64; + LPWSTR modpath = NULL; + char *retval = NULL; + DWORD rc = 0; + + while (true) + { + void *ptr = xrealloc(modpath, buflen * sizeof(WCHAR)); + + modpath = (LPWSTR) ptr; + + rc = pGetModuleFileNameW(NULL, modpath, buflen); + if (rc == 0) + { + free(modpath); + return NULL; + } // if + + if (rc < buflen) + { + buflen = rc; + break; + } // if + + buflen *= 2; + } // while + + if (buflen > 0) // just in case... + { + WCHAR *ptr = (modpath + buflen) - 1; + while (ptr != modpath) + { + if (*ptr == '\\') + break; + ptr--; + } // while + + if ((ptr != modpath) || (*ptr == '\\')) // should always be true... + { + *(ptr + 1) = '\0'; // chop off filename. + retval = unicodeToUtf8Heap(modpath); + } // else + } // else + + free(modpath); + return(retval); +} // MojoPlatform_appBinaryPath + + +// Try to make use of GetUserProfileDirectoryW(), which isn't available on +// some common variants of Win32. If we can't use this, we just punt and +// use the binary path 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. + +char *MojoPlatform_homedir(void) +{ + char *userDir = NULL; + + // GetUserProfileDirectoryW() 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. Since this is originally an NT API, we don't + // offer a non-Unicode fallback. + + if (pGetUserProfileDirectoryW != NULL) + { + HANDLE accessToken = NULL; // Security handle to process + HANDLE processHandle = GetCurrentProcess(); + if (OpenProcessToken(processHandle, TOKEN_QUERY, &accessToken)) + { + DWORD psize = 0; + WCHAR dummy = 0; + LPWSTR wstr = NULL; + BOOL rc = 0; + + // 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 = pGetUserProfileDirectoryW(accessToken, &dummy, &psize); + if (rc == 0) // this should always be true! + { + // Allocate memory for the profile directory + wstr = (LPWSTR) smallAlloc(psize * sizeof (WCHAR)); + if (wstr != NULL) + { + if (pGetUserProfileDirectoryW(accessToken, wstr, &psize)) + userDir = unicodeToUtf8Heap(wstr); + smallFree(wstr); + } // else + } // if + + CloseHandle(accessToken); + } // if + } // if + + if (userDir == NULL) // couldn't get profile for some reason. + { + // Might just be a non-NT system; try SHGetFolderPathA()... + if (pSHGetFolderPath != NULL) // can be NULL if IE5+ isn't installed! + { + char shellPath[MAX_PATH]; + HRESULT status = pSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, + SHGFP_TYPE_CURRENT, shellPath); + if (SUCCEEDED(status)) + userDir = codepageToUtf8Heap(shellPath); + } // if + } // if + + if (userDir == NULL) // Still nothing?! + { + // this either means we had a catastrophic failure, or we're on a + // Win95 system without at least Internet Explorer 5.0. Bleh! + userDir = xstrdup("C:\\My Documents"); // good luck with that. + } // if + + return userDir; +} // MojoPlatform_homedir + + +// This implementation is a bit naive. +boolean MojoPlatform_locale(char *buf, size_t len) +{ + boolean retval = false; + char lang[16]; + char country[16]; + + const int langrc = GetLocaleInfoA(LOCALE_USER_DEFAULT, + LOCALE_SISO639LANGNAME, + lang, sizeof (lang)); + + const int ctryrc = GetLocaleInfoA(LOCALE_USER_DEFAULT, + LOCALE_SISO3166CTRYNAME, + country, sizeof (country)); + + // Win95 systems will fail, because they don't have LOCALE_SISO*NAME ... + if (langrc != 0) && (ctryrc != 0) + { + snprintf(buf, len, "%s_%s", lang, country); + retval = true; + } // if + + return retval; +} // MojoPlatform_locale + + +boolean MojoPlatform_osType(char *buf, size_t len) +{ + if (osIsWin9x) + xstrncpy(buf, "win9x", len); + else + xstrncpy(buf, "winnt", len); + + return true; +} // MojoPlatform_ostype + + +boolean MojoPlatform_osVersion(char *buf, size_t len) +{ + snprintf(buf, len, "%u.%u.%u", + (unsigned int) osMajorVer, + (unsigned int) osMinorVer, + (unsigned int) osBuildVer); + return true; +} // MojoPlatform_osversion + + +void MojoPlatform_sleep(uint32 ticks) +{ + Sleep(ticks); +} // MojoPlatform_sleep + + +uint32 MojoPlatform_ticks(void) +{ + return GetTickCount() - startupTime; +} // MojoPlatform_ticks + + +void MojoPlatform_die(void) +{ + STUBBED("Win32 equivalent of _exit()?"); + _exit(86); +} // MojoPlatform_die + + +boolean MojoPlatform_unlink(const char *fname) +{ + int retval = 0; + LPWSTR wpath; + UTF8_TO_UNICODE_STACK_MACRO(wpath, fname); + if (pGetFileAttributesW(wpath) == FILE_ATTRIBUTE_DIRECTORY) + retval = (pRemoveDirectoryW(wpath) != 0); + else + retval = (pDeleteFileW(wpath) != 0); + smallFree(wpath); + return retval; +} // MojoPlatform_unlink + + +boolean MojoPlatform_symlink(const char *src, const char *dst) +{ + STUBBED("Vista has symlink support"); + return false; +} // MojoPlatform_symlink + + +boolean MojoPlatform_mkdir(const char *path, uint16 perms) +{ + // !!! FIXME: error if already exists? + // !!! FIXME: perms? + WCHAR *wpath; + DWORD rc; + UTF8_TO_UNICODE_STACK_MACRO(wpath, path); + rc = pCreateDirectoryW(wpath, NULL); + smallFree(wpath); + return (rc != 0); +} // MojoPlatform_mkdir + + +boolean MojoPlatform_rename(const char *src, const char *dst) +{ + WCHAR *srcwpath; + WCHAR *dstwpath; + BOOL rc; + MojoPlatform_unlink(dst); // to match Unix rename()... + UTF8_TO_UNICODE_STACK_MACRO(srcwpath, src); + UTF8_TO_UNICODE_STACK_MACRO(dstwpath, dst); + rc = pMoveFileW(srcwpath, dstwpath); + smallFree(srcwpath); + smallFree(dstwpath); + return (rc != 0); +} // MojoPlatform_rename + + +boolean MojoPlatform_exists(const char *dir, const char *fname) +{ + WCHAR *wpath; + char *fullpath = NULL; + boolean retval = false; + + if (fname == NULL) + fullpath = xstrdup(dir); + else + { + const size_t len = strlen(dir) + strlen(fname) + 1; + fullpath = (char *) xmalloc(len); + snprintf(fullpath, len, "%s\\%s", dir, fname); + } // else + + UTF8_TO_UNICODE_STACK_MACRO(wpath, fullpath); + retval = (pGetFileAttributesW(wpath) == INVALID_FILE_ATTRIBUTES); + smallFree(wpath); + free(fullpath); + + return retval; +} // MojoPlatform_exists + + +boolean MojoPlatform_writable(const char *fname) +{ + boolean retval = false; + DWORD attr = 0; + WCHAR *wpath; + UTF8_TO_UNICODE_STACK_MACRO(wpath, fname); + attr = pGetFileAttributesW(wpath); + smallFree(wpath); + if (attr != INVALID_FILE_ATTRIBUTES) + retval = ((attr & FILE_ATTRIBUTE_READONLY) == 0); + return retval; +} // MojoPlatform_writable + + +boolean MojoPlatform_isdir(const char *dir) +{ + boolean retval = false; + LPWSTR wpath; + UTF8_TO_UNICODE_STACK_MACRO(wpath, dir); + retval = ((pGetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY) != 0); + smallFree(wpath); + return retval; +} // MojoPlatform_isdir + + +static boolean isSymlinkAttrs(const DWORD attr, const DWORD tag) +{ + return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) && + (tag == PHYSFS_IO_REPARSE_TAG_SYMLINK) ); +} // isSymlinkAttrs + + +boolean MojoPlatform_issymlink(const char *fname) +{ + /* !!! FIXME: + * Windows Vista can have NTFS symlinks. Can older Windows releases have + * them when talking to a network file server? What happens when you + * mount a NTFS partition on XP that was plugged into a Vista install + * that made a symlink? + */ + + boolean retval = false; + LPWSTR wpath; + HANDLE dir; + WIN32_FIND_DATAW entw; + + // no unicode entry points? Probably no symlinks. + if (pFindFirstFileW == NULL) + return false; + + // !!! FIXME: filter wildcard chars? + UTF8_TO_UNICODE_STACK_MACRO(wpath, fname); + dir = pFindFirstFileW(wpath, &entw); + smallFree(wpath); + + if (dir != INVALID_HANDLE_VALUE) + { + retval = isSymlinkAttrs(entw.dwFileAttributes, entw.dwReserved0); + FindClose(dir); + } // if + + return retval; +} // MojoPlatform_issymlink + + +boolean MojoPlatform_isfile(const char *dir) +{ + return ((!MojoPlatform_isdir(dir)) && (!MojoPlatform_issymlink(dir))); +} // MojoPlatform_isfile + + +void *MojoPlatform_open(const char *fname, uint32 flags, uint16 mode) +{ + HANDLE *retval = NULL; + DWORD accessMode = 0; + DWORD createMode = 0; + DWORD shareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; + WCHAR *wpath = NULL; + HANDLE fd = 0; + + if (flags & MOJOFILE_READ) + accessMode |= GENERIC_READ; + if (flags & MOJOFILE_WRITE) + accessMode |= GENERIC_WRITE; + if (accessMode == 0) + return NULL; // have to specify SOMETHING. + +// if (flags & MOJOFILE_APPEND) +// unixflags |= O_APPEND; + + if ((flags & MOJOFILE_CREATE) && (flags & MOJOFILE_EXCLUSIVE)) + createMode = CREATE_NEW; + else if ((flags & MOJOFILE_CREATE) && (flags & MOJOFILE_TRUNCATE)) + createMode = CREATE_ALWAYS; + else if (flags & MOJOFILE_CREATE) + createMode = OPEN_ALWAYS; + else if (flags & MOJOFILE_TRUNCATE) + createMode = TRUNCATE_EXISTING; + else + createMode = OPEN_EXISTING; + + // !!! FIXME + STUBBED("file permissions"); + + UTF8_TO_UNICODE_STACK_MACRO(wpath, fname); + fd = pCreateFileW(wpath, accessMode, shareMode, NULL, createMode, + FILE_ATTRIBUTE_NORMAL, NULL); + smallFree(wpath); + + if (fd != INVALID_HANDLE_VALUE) + { + retval = (HANDLE *) xmalloc(sizeof (HANDLE)); + *retval = fd; + } // if + + return retval; +} // MojoPlatform_open + + +int64 MojoPlatform_read(void *fd, void *buf, uint32 bytes) +{ + HANDLE handle = *((HANDLE *) fd); + DWORD br = 0; + + // Read data from the file + // !!! FIXME: uint32 might be a greater # than DWORD + if(!ReadFile(handle, buf, bytes, &br, NULL)) + return -1; + + return (int64) br; +} // MojoPlatform_read + + +int64 MojoPlatform_write(void *fd, const void *buf, uint32 bytes) +{ + HANDLE handle = *((HANDLE *) fd); + DWORD bw = 0; + + // Read data from the file + // !!! FIXME: uint32 might be a greater # than DWORD + if(!WriteFile(handle, buf, bytes, &bw, NULL)) + return -1; + + return (int64) bw; +} // MojoPlatform_write + + +int64 MojoPlatform_tell(void *fd) +{ + return MojoPlatform_seek(fd, 0, MOJOSEEK_CURRENT); +} // MojoPlatform_tell + + +int64 MojoPlatform_seek(void *fd, int64 offset, MojoFileSeek whence) +{ + HANDLE handle = *((HANDLE *) fd); + DWORD HighOrderPos = HIGHORDER_UINT64(pos); + DWORD winwhence = 0; + DWORD rc = 0; + + switch (whence) + { + case MOJOSEEK_SET: winwhence = FILE_BEGIN; break; + case MOJOSEEK_CURRENT: winwhence = FILE_CURRENT; break; + case MOJOSEEK_END: winwhence = FILE_END; break; + default: return -1; // !!! FIXME: maybe just abort? + } // switch + + rc = SetFilePointer(handle,LOWORDER_UINT64(pos),&HighOrderPos,winwhence); + if ( (rc == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) + return -1; + + return (int64) ((((uint64) HighOrderPos) << 32) | ((uint64) rc)); +} // MojoPlatform_seek + + +int64 MojoPlatform_flen(void *fd) +{ + HANDLE handle = *((HANDLE *) fd); + int64 retval = 0; + DWORD SizeHigh = 0; + DWORD SizeLow = GetFileSize(handle, &SizeHigh); + + if ((SizeLow == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) + return -1; + else + { + // Combine the high/low order to create the 64-bit position value + retval = (int64) ((((uint64) SizeHigh) << 32) | ((uint64) SizeLow)); + assert(retval >= 0); + } // else + + return retval; +} // MojoPlatform_flen + + +boolean MojoPlatform_flush(void *fd) +{ + HANDLE handle = *((HANDLE *) fd); + return (FlushFileBuffers(handle) != 0); +} // MojoPlatform_flush + + +boolean MojoPlatform_close(void *fd) +{ + HANDLE handle = *((HANDLE *) fd); + boolean retval = (CloseHandle(handle) != 0); + if (retval) + free(fd); + return retval; +} // MojoPlatform_close + + +typedef struct +{ + HANDLE dir; + boolean done; + WIN32_FIND_DATA ent; + WIN32_FIND_DATAW entw; +} WinApiDir; + +void *MojoPlatform_opendir(const char *dirname) +{ + const int unicode = (pFindFirstFileW != NULL) && (pFindNextFileW != NULL); + size_t len = strlen(dirname); + char *searchPath = NULL; + WCHAR *wSearchPath = NULL; + WinApiDir *retval = (WinApiDir *) xmalloc(sizeof (WinApiDir)); + + retval->dir = INVALID_HANDLE_VALUE; + retval->done = false; + + // Allocate a new string for path, maybe '\\', "*", and NULL terminator + searchPath = (char *) smallAlloc(len + 3); + + // 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, "*"); + + UTF8_TO_UNICODE_STACK_MACRO(wSearchPath, searchPath); + + if (unicode) + retval->dir = pFindFirstFileW(wSearchPath, &retval->entw); + else + { + const int len = (int) (wStrLen(wSearchPath) + 1); + char *cp = (char *) smallAlloc(len); + WideCharToMultiByte(CP_ACP, 0, wSearchPath, len, cp, len, 0, 0); + retval->dir = FindFirstFileA(cp, &retval->ent); + smallFree(cp); + } // else + + smallFree(wSearchPath); + smallFree(searchPath); + if (retval->dir == INVALID_HANDLE_VALUE) + { + free(retval); + return NULL; + } // if + + return retval; +} // MojoPlatform_opendir + + +char *MojoPlatform_readdir(void *_dirhandle) +{ + const int unicode = (pFindFirstFileW != NULL) && (pFindNextFileW != NULL); + const WinApiDir *dir = (WinApiDir *) _dirhandle; + char *utf8 = NULL; + + if (dir->done) + return NULL; + + if (unicode) + { + do + { + const DWORD attr = dir->entw.dwFileAttributes; + const DWORD tag = dir->entw.dwReserved0; + const WCHAR *fn = dir->entw.cFileName; + if ((fn[0] == '.') && (fn[1] == '\0')) + continue; + if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) + continue; + + utf8 = unicodeToUtf8Heap(fn); + dir->done = (pFindNextFileW(dir->dir, &dir->entw) == 0); + return utf8; + } while (pFindNextFileW(dir->dir, &dir->entw) != 0); + } // if + + else // ANSI fallback. + { + do + { + const DWORD attr = ent.dwFileAttributes; + const DWORD tag = ent.dwReserved0; + const char *fn = ent.cFileName; + if ((fn[0] == '.') && (fn[1] == '\0')) + continue; + if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) + continue; + + utf8 = codepageToUtf8Heap(fn); + dir->done = (FindNextFileA(dir, &ent) == 0); + return utf8; + } while (FindNextFileA(dir, &ent) != 0); + } // else + + dir->done = true; + return NULL; +} // MojoPlatform_readdir + + +void MojoPlatform_closedir(void *dirhandle) +{ + WinApiDir *dir = (WinApiDir *) dirhandle; + if (dir) + { + FindClose(dir->dir); + free(dir); + } // if +} // MojoPlatform_closedir + + +int64 MojoPlatform_filesize(const char *fname) +{ + // !!! FIXME: this is lame. + int64 retval = -1; + void *fd = MojoPlatform_open(const char *fname, MOJOFILE_READ, 0); + STUBBED("use a stat()-like thing instead"); + if (fd != NULL) + { + retval = MojoPlatform_seek(fd, 0, MOJOSEEK_END); + MojoPlatform_close(fd); + } // if + + return retval; +} // MojoPlatform_filesize + + +boolean MojoPlatform_perms(const char *fname, uint16 *p) +{ + STUBBED("Windows permissions"); + *p = 0; + return true; +} // MojoPlatform_perms + + +uint16 MojoPlatform_defaultFilePerms(void) +{ + STUBBED("Windows permissions"); + return 0644; +} // MojoPlatform_defaultFilePerms + + +uint16 MojoPlatform_defaultDirPerms(void) +{ + STUBBED("Windows permissions"); + return 0755; +} // MojoPlatform_defaultDirPerms + + +uint16 MojoPlatform_makePermissions(const char *str, boolean *_valid) +{ + STUBBED("Windows permissions"); + *_valid = true; + return 0; +} // MojoPlatform_makePermissions + + +boolean MojoPlatform_chmod(const char *fname, uint16 p) +{ + STUBBED("Windows permissions"); + return true; + //return (chmod(fname, p) != -1); +} // MojoPlatform_chmod + + +static BOOL mediaInDrive(const char *drive) +{ + // Prevent windows warning message appearing when checking media size + UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); + DWORD tmp = 0; + // If the function succeeds, there's media in the drive + BOOL retval = GetVolumeInformationA(drive,NULL,0,NULL,NULL,&tmp,NULL,0); + + // Revert back to old windows error handler + SetErrorMode(oldErrorMode); + return retval; +} // mediaInDrive + + +char *MojoPlatform_findMedia(const char *uniquefile) +{ + // !!! FIXME: Probably shouldn't just check drive letters... + + char drive_str[4] = { 'x', ':', '\\', '\0' }; + char ch; + UINT rc; + boolean found = false; + + for (ch = 'A'; ch <= 'Z'; ch++) + { + drive_str[0] = ch; + rc = GetDriveTypeA(drive_str); + if ((rc != DRIVE_UNKNOWN) && (rc != DRIVE_NO_ROOT_DIR)) + { + if (mediaInDrive(drive_str)) + { + drive_str[2] = '\0'; + found = (MojoPlatform_exists(drive_str, uniquefile)); + drive_str[2] = '\\'; + if (found) + return xstrdup(drive_str); + } // if + } // if + } // for + + return NULL; +} // MojoPlatform_findMedia + + +void MojoPlatform_log(const char *str) +{ + if (pOutputDebugStringW != NULL) // in case this gets called before init... + { + WCHAR *wstr; + UTF8_TO_UNICODE_STACK_MACRO(wstr, str); + STUBBED("OutputDebugString() is probably not best here"); + pOutputDebugStringW(wstr); + smallFree(wstr); + } // if +} // MojoPlatform_log + + +typedef struct +{ + HINSTANCE dll; + HANDLE file; +} WinApiDll; + +void *MojoPlatform_dlopen(const uint8 *img, size_t len) +{ + WinApiDll *retval = NULL; + char path[MAX_PATH]; + char fname[MAX_PATH]; + DWORD bw = 0; + HANDLE handle; + HINSTANCE dll; + + GetTempPath(sizeof (path), path); + GetTempFileName(path, "mojosetup-plugin-", 0, fname); + + handle = CreateFileA(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (handle == INVALID_HANDLE_VALUE) + return NULL; + + WriteFile(handle, img, len, &bw, NULL); // dump it to the temp file. + + CloseHandle(handle); + if (bw != len) + { + DeleteFile(fname); + return NULL; + } // if + + // The DELETE_ON_CLOSE will cause the kernel to remove the file when + // we're done with it, including manually closing or the process + // terminating (including crashing). We hold this handle until we close + // the library. + handle = CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (handle == INVALID_HANDLE_VALUE) + { + DeleteFile(fname); + return NULL; + } // if + + dll = LoadLibraryA(fname); + if (dll == NULL) + { + CloseHandle(handle); // (also deletes temp file.) + return NULL; + } // if + + retval = (WinApiDll *) xmalloc(sizeof (WinApiDll)); + retval->dll = dll; + retval->file = handle; + return retval; +} // MojoPlatform_dlopen + + +void *MojoPlatform_dlsym(void *_lib, const char *sym) +{ + const WinApiDll *lib = (const WinApiDll *) _lib; + return ((lib) ? GetProcAddress(lib->dll, sym) : NULL); +} // MojoPlatform_dlsym + + +void MojoPlatform_dlclose(void *_lib) +{ + const WinApiDll *lib = (const WinApiDll *) _lib; + if (lib) + { + FreeLibrary(lib->dll); + CloseHandle(lib->handle); // this also deletes the temp file. + free(lib); + } // if +} // MojoPlatform_dlclose + + +// Get OS info and save the important parts. +// Returns non-zero if successful, otherwise it returns zero on failure. +static boolean getOSInfo(void) +{ + OSVERSIONINFO osVerInfo; + osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); + if (!GetVersionEx(&osVerInfo)) + return false; + + osIsWin9x = (osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); + osMajorVer = (uint32) osVerInfo.dwMajorVersion; + osMinorVer = (uint32) osVerInfo.dwMinorVersion; + osBuildVer = (uint32) osVerInfo.dwBuildNumber; + + return true; +} // getOSInfo + + +static boolean platformInit(void) +{ + startupTime = GetTickCount(); + + if (!getOSInfo()) + return false; + + if (!findApiSymbols()) + return false; + + return true; +} // platformInit + + +static void platformDeinit(void) +{ + HANDLE *libs[] = { &libKernel32, &libUserEnv, &libAdvApi32, &libShell32 }; + int i; + + for (i = 0; i < (sizeof (libs) / sizeof (libs[0])); i++) + { + const HANDLE lib = *(libs[i]); + if (lib) + { + FreeLibrary(lib); + *(libs[i]) = NULL; + } // if + } // for +} // platformDeinit + + +static void buildCommandlineArray(LPSTR szCmd, int *_argc, char **_argv) +{ + int argc = 0; + char **argv = NULL; + + // !!! FIXME: STUBBED("parse command line string into array"); + + *_argc = argc; + *_argv = argv; +} // buildCommandlineArray + + +static void freeCommandlineArray(int argc, char **argv) +{ + while (argc--) + free(argv[argc]); + free(argv); +} // freeCommandlineArray + + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmd, int nCmdShow) +{ + int retval = 0; + int argc = 0; + char **argv = NULL; + + if (!platformInit()) + retval = 1; + else + { + buildCommandlineArray(szCmd, &argc, &argv); + //openlog("mojosetup", LOG_PID, LOG_USER); + //atexit(closelog); + STUBBED("signal handlers"); + //install_signals(); + retval = MojoSetup_main(argc, argv); + freeCommandlineArray(argc, argv); + + platformDeinit(); + } // else + + return retval; +} // main + +#endif // PLATFORM_WINDOWS + +// end of windows.c ... + From DONOTREPLY at icculus.org Wed Sep 26 05:03:56 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 05:03:56 -0400 Subject: r353 - trunk Message-ID: <20070926090356.9540.qmail@icculus.org> Author: icculus Date: 2007-09-26 05:03:55 -0400 (Wed, 26 Sep 2007) New Revision: 353 Modified: trunk/CMakeLists.txt Log: Added platform_windows.c to build. Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 09:02:35 UTC (rev 352) +++ trunk/CMakeLists.txt 2007-09-26 09:03:55 UTC (rev 353) @@ -189,6 +189,7 @@ checksum_sha1.c platform_unix.c platform_beos.c + platform_windows.c lua_glue.c ${LUA_SRCS} ) From DONOTREPLY at icculus.org Wed Sep 26 15:23:55 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 15:23:55 -0400 Subject: r354 - trunk Message-ID: <20070926192355.30601.qmail@icculus.org> Author: icculus Date: 2007-09-26 15:23:55 -0400 (Wed, 26 Sep 2007) New Revision: 354 Modified: trunk/CMakeLists.txt Log: Don't compile stdio stuff in bzlib; we don't use it, and it throws warnings about POSIX vs ISO function names on VS.NET 2005. Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 09:03:55 UTC (rev 353) +++ trunk/CMakeLists.txt 2007-09-26 19:23:55 UTC (rev 354) @@ -426,6 +426,7 @@ OPTION(MOJOSETUP_ARCHIVE_TAR_BZ2 "Enable TAR.BZ2 support" TRUE) IF(MOJOSETUP_ARCHIVE_TAR_BZ2) ADD_DEFINITIONS(-DSUPPORT_TAR_BZ2=1) + ADD_DEFINITIONS(-DBZ_NO_STDIO=1) SET(MOJOSETUP_NEED_BZLIB TRUE) ENDIF(MOJOSETUP_ARCHIVE_TAR_BZ2) ENDIF(MOJOSETUP_ARCHIVE_TAR) From DONOTREPLY at icculus.org Wed Sep 26 16:03:04 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 16:03:04 -0400 Subject: r355 - trunk Message-ID: <20070926200304.27486.qmail@icculus.org> Author: icculus Date: 2007-09-26 16:03:04 -0400 (Wed, 26 Sep 2007) New Revision: 355 Modified: trunk/CMakeLists.txt Log: Need Winsock library for gui_www on Windows. Not sure if this is right... Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 19:23:55 UTC (rev 354) +++ trunk/CMakeLists.txt 2007-09-26 20:03:04 UTC (rev 355) @@ -395,8 +395,14 @@ IF(MOJOSETUP_GUI_WWW_STATIC) ADD_DEFINITIONS(-DGUI_STATIC_LINK_WWW=1) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_www.c) + IF(WINDOWS) + SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} winsock) + ENDIF(WINDOWS) ELSE(MOJOSETUP_GUI_WWW_STATIC) MOJOSETUP_ADD_LIBRARY(mojosetupgui_www gui_www.c) + IF(WINDOWS) + TARGET_LINK_LIBRARIES(mojosetupgui_www winsock) + ENDIF(WINDOWS) ENDIF(MOJOSETUP_GUI_WWW_STATIC) ENDIF(MOJOSETUP_GUI_WWW) From DONOTREPLY at icculus.org Wed Sep 26 16:05:44 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 16:05:44 -0400 Subject: r356 - trunk Message-ID: <20070926200544.29176.qmail@icculus.org> Author: icculus Date: 2007-09-26 16:05:44 -0400 (Wed, 26 Sep 2007) New Revision: 356 Modified: trunk/CMakeLists.txt Log: Apparently it's "wsock32" and not "winsock" ... Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 20:03:04 UTC (rev 355) +++ trunk/CMakeLists.txt 2007-09-26 20:05:44 UTC (rev 356) @@ -396,12 +396,12 @@ ADD_DEFINITIONS(-DGUI_STATIC_LINK_WWW=1) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_www.c) IF(WINDOWS) - SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} winsock) + SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} wsock32) ENDIF(WINDOWS) ELSE(MOJOSETUP_GUI_WWW_STATIC) MOJOSETUP_ADD_LIBRARY(mojosetupgui_www gui_www.c) IF(WINDOWS) - TARGET_LINK_LIBRARIES(mojosetupgui_www winsock) + TARGET_LINK_LIBRARIES(mojosetupgui_www wsock32) ENDIF(WINDOWS) ENDIF(MOJOSETUP_GUI_WWW_STATIC) ENDIF(MOJOSETUP_GUI_WWW) From DONOTREPLY at icculus.org Wed Sep 26 16:13:26 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 16:13:26 -0400 Subject: r357 - trunk Message-ID: <20070926201326.1240.qmail@icculus.org> Author: icculus Date: 2007-09-26 16:13:24 -0400 (Wed, 26 Sep 2007) New Revision: 357 Modified: trunk/CMakeLists.txt trunk/mojosetup.c Log: Fixed missing bzlib symbol. Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 20:05:44 UTC (rev 356) +++ trunk/CMakeLists.txt 2007-09-26 20:13:24 UTC (rev 357) @@ -512,6 +512,7 @@ # BINARY SIZE += 46 IF(MOJOSETUP_INTERNAL_BZLIB) + ADD_DEFINITION(-DMOJOSETUP_INTERNAL_BZLIB=1) INCLUDE_DIRECTORIES(${BZLIB_DIR}) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${BZLIB_SRCS}) ELSE(MOJOSETUP_INTERNAL_BZLIB) Modified: trunk/mojosetup.c =================================================================== --- trunk/mojosetup.c 2007-09-26 20:05:44 UTC (rev 356) +++ trunk/mojosetup.c 2007-09-26 20:13:24 UTC (rev 357) @@ -555,6 +555,15 @@ } // xstrdup +// We have to supply this function under certain build types. +#if MOJOSETUP_INTERNAL_BZLIB && BZ_NO_STDIO +void bz_internal_error(int errcode) +{ + fatal(_("bzlib triggered an internal error: %d", errcode)); +} // bz_internal_error +#endif + + // This is called from main()/WinMain()/whatever. int MojoSetup_main(int argc, char **argv) { From DONOTREPLY at icculus.org Wed Sep 26 16:13:57 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 16:13:57 -0400 Subject: r358 - trunk Message-ID: <20070926201357.1555.qmail@icculus.org> Author: icculus Date: 2007-09-26 16:13:57 -0400 (Wed, 26 Sep 2007) New Revision: 358 Modified: trunk/CMakeLists.txt Log: Crap, typo. Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 20:13:24 UTC (rev 357) +++ trunk/CMakeLists.txt 2007-09-26 20:13:57 UTC (rev 358) @@ -512,7 +512,7 @@ # BINARY SIZE += 46 IF(MOJOSETUP_INTERNAL_BZLIB) - ADD_DEFINITION(-DMOJOSETUP_INTERNAL_BZLIB=1) + ADD_DEFINITIONS(-DMOJOSETUP_INTERNAL_BZLIB=1) INCLUDE_DIRECTORIES(${BZLIB_DIR}) SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${BZLIB_SRCS}) ELSE(MOJOSETUP_INTERNAL_BZLIB) From DONOTREPLY at icculus.org Wed Sep 26 16:21:02 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 16:21:02 -0400 Subject: r359 - trunk Message-ID: <20070926202102.7231.qmail@icculus.org> Author: icculus Date: 2007-09-26 16:21:02 -0400 (Wed, 26 Sep 2007) New Revision: 359 Modified: trunk/mojosetup.c trunk/platform_windows.c Log: Patched Windows code to compile (doesn't link yet). Modified: trunk/mojosetup.c =================================================================== --- trunk/mojosetup.c 2007-09-26 20:13:57 UTC (rev 358) +++ trunk/mojosetup.c 2007-09-26 20:21:02 UTC (rev 359) @@ -559,7 +559,7 @@ #if MOJOSETUP_INTERNAL_BZLIB && BZ_NO_STDIO void bz_internal_error(int errcode) { - fatal(_("bzlib triggered an internal error: %d", errcode)); + fatal(_("bzlib triggered an internal error: %d"), errcode); } // bz_internal_error #endif Modified: trunk/platform_windows.c =================================================================== --- trunk/platform_windows.c 2007-09-26 20:13:57 UTC (rev 358) +++ trunk/platform_windows.c 2007-09-26 20:21:02 UTC (rev 359) @@ -32,16 +32,14 @@ // These allocation macros are much more complicated in PhysicsFS. #define smallAlloc(x) xmalloc(x) -#define smallFree(x) xfree(x) +#define smallFree(x) free(x) // ...so is this. #define BAIL_IF_MACRO(cond, err, ret) if (cond) return ret; #define BAIL_MACRO(err, ret) return ret; -#define LOWORDER_UINT64(pos) (PHYSFS_uint32) \ - (pos & 0x00000000FFFFFFFF) -#define HIGHORDER_UINT64(pos) (PHYSFS_uint32) \ - (((pos & 0xFFFFFFFF00000000) >> 32) & 0x00000000FFFFFFFF) +#define LOWORDER_UINT64(pos) ((uint32) (pos & 0xFFFFFFFF)) +#define HIGHORDER_UINT64(pos) ((uint32) ((pos >> 32) & 0xFFFFFFFF)) /* * Users without the platform SDK don't have this defined. The original docs @@ -62,20 +60,29 @@ #define IO_REPARSE_TAG_SYMLINK 0xA000000C #endif +// This is in shlobj.h, but we can't include it due to universal.h conflicts. +#ifndef CSIDL_PERSONAL +#define CSIDL_PERSONAL 0x0005 +#endif + +#ifndef SHGFP_TYPE_CURRENT +#define SHGFP_TYPE_CURRENT 0x0000 +#endif + #define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \ if (str == NULL) \ w_assignto = NULL; \ else { \ - const uint64 len = (uint64) ((strlen(str) * 4) + 1); \ + const uint32 len = (uint32) ((strlen(str) * 4) + 1); \ w_assignto = (WCHAR *) smallAlloc(len); \ if (w_assignto != NULL) \ utf8ToUcs2(str, (uint16 *) w_assignto, len); \ } \ } \ -static uint64 wStrLen(const WCHAR *wstr) +static uint32 wStrLen(const WCHAR *wstr) { - uint64 len = 0; + uint32 len = 0; while (*(wstr++)) len++; return(len); @@ -88,7 +95,7 @@ if (w_str != NULL) { void *ptr = NULL; - const uint64 len = (wStrLen(w_str) * 4) + 1; + const uint32 len = (wStrLen(w_str) * 4) + 1; retval = (char *) xmalloc(len); utf8FromUcs2((const uint16 *) w_str, retval, len); retval = xrealloc(retval, strlen(retval) + 1); // shrink. @@ -281,7 +288,7 @@ const int buflen = (int) (wStrLen(str) + 1); char *cpstr = (char *) smallAlloc(buflen); WideCharToMultiByte(CP_ACP, 0, str, buflen, cpstr, buflen, NULL, NULL); - retval = OutputDebugStringA(cpstr); + OutputDebugStringA(cpstr); smallFree(cpstr); } // fallbackOutputDebugStringW @@ -357,8 +364,6 @@ // ok, now the actual platform layer implementation... -static struct timeval startup_time; - char *MojoPlatform_currentWorkingDir(void) { char *retval = NULL; @@ -615,11 +620,11 @@ if (userDir == NULL) // couldn't get profile for some reason. { // Might just be a non-NT system; try SHGetFolderPathA()... - if (pSHGetFolderPath != NULL) // can be NULL if IE5+ isn't installed! + if (pSHGetFolderPathA != NULL) // can be NULL if IE5+ isn't installed! { char shellPath[MAX_PATH]; - HRESULT status = pSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, - SHGFP_TYPE_CURRENT, shellPath); + HRESULT status = pSHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, + SHGFP_TYPE_CURRENT, shellPath); if (SUCCEEDED(status)) userDir = codepageToUtf8Heap(shellPath); } // if @@ -652,7 +657,7 @@ country, sizeof (country)); // Win95 systems will fail, because they don't have LOCALE_SISO*NAME ... - if (langrc != 0) && (ctryrc != 0) + if ((langrc != 0) && (ctryrc != 0)) { snprintf(buf, len, "%s_%s", lang, country); retval = true; @@ -803,7 +808,7 @@ static boolean isSymlinkAttrs(const DWORD attr, const DWORD tag) { return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) && - (tag == PHYSFS_IO_REPARSE_TAG_SYMLINK) ); + (tag == IO_REPARSE_TAG_SYMLINK) ); } // isSymlinkAttrs @@ -928,10 +933,11 @@ } // MojoPlatform_tell -int64 MojoPlatform_seek(void *fd, int64 offset, MojoFileSeek whence) +int64 MojoPlatform_seek(void *fd, int64 pos, MojoFileSeek whence) { HANDLE handle = *((HANDLE *) fd); - DWORD HighOrderPos = HIGHORDER_UINT64(pos); + DWORD highpos = HIGHORDER_UINT64(pos); + const DWORD lowpos = LOWORDER_UINT64(pos); DWORD winwhence = 0; DWORD rc = 0; @@ -943,11 +949,11 @@ default: return -1; // !!! FIXME: maybe just abort? } // switch - rc = SetFilePointer(handle,LOWORDER_UINT64(pos),&HighOrderPos,winwhence); + rc = SetFilePointer(handle, lowpos, &highpos, winwhence); if ( (rc == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) return -1; - return (int64) ((((uint64) HighOrderPos) << 32) | ((uint64) rc)); + return (int64) ((((uint64) highpos) << 32) | ((uint64) rc)); } // MojoPlatform_seek @@ -1051,7 +1057,7 @@ char *MojoPlatform_readdir(void *_dirhandle) { const int unicode = (pFindFirstFileW != NULL) && (pFindNextFileW != NULL); - const WinApiDir *dir = (WinApiDir *) _dirhandle; + WinApiDir *dir = (WinApiDir *) _dirhandle; char *utf8 = NULL; if (dir->done) @@ -1079,18 +1085,18 @@ { do { - const DWORD attr = ent.dwFileAttributes; - const DWORD tag = ent.dwReserved0; - const char *fn = ent.cFileName; + const DWORD attr = dir->ent.dwFileAttributes; + const DWORD tag = dir->ent.dwReserved0; + const char *fn = dir->ent.cFileName; if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) continue; utf8 = codepageToUtf8Heap(fn); - dir->done = (FindNextFileA(dir, &ent) == 0); + dir->done = (FindNextFileA(dir->dir, &dir->ent) == 0); return utf8; - } while (FindNextFileA(dir, &ent) != 0); + } while (FindNextFileA(dir->dir, &dir->ent) != 0); } // else dir->done = true; @@ -1113,7 +1119,7 @@ { // !!! FIXME: this is lame. int64 retval = -1; - void *fd = MojoPlatform_open(const char *fname, MOJOFILE_READ, 0); + void *fd = MojoPlatform_open(fname, MOJOFILE_READ, 0); STUBBED("use a stat()-like thing instead"); if (fd != NULL) { @@ -1286,11 +1292,11 @@ void MojoPlatform_dlclose(void *_lib) { - const WinApiDll *lib = (const WinApiDll *) _lib; + WinApiDll *lib = (WinApiDll *) _lib; if (lib) { FreeLibrary(lib->dll); - CloseHandle(lib->handle); // this also deletes the temp file. + CloseHandle(lib->file); // this also deletes the temp file. free(lib); } // if } // MojoPlatform_dlclose @@ -1345,7 +1351,7 @@ } // platformDeinit -static void buildCommandlineArray(LPSTR szCmd, int *_argc, char **_argv) +static void buildCommandlineArray(LPSTR szCmd, int *_argc, char ***_argv) { int argc = 0; char **argv = NULL; From DONOTREPLY at icculus.org Wed Sep 26 18:19:35 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 18:19:35 -0400 Subject: r360 - trunk Message-ID: <20070926221935.5397.qmail@icculus.org> Author: icculus Date: 2007-09-26 18:19:35 -0400 (Wed, 26 Sep 2007) New Revision: 360 Modified: trunk/platform_windows.c Log: utf-8 to/from ucs-2 conversion code. Untested, may not compile. Modified: trunk/platform_windows.c =================================================================== --- trunk/platform_windows.c 2007-09-26 20:21:02 UTC (rev 359) +++ trunk/platform_windows.c 2007-09-26 22:19:35 UTC (rev 360) @@ -69,6 +69,275 @@ #define SHGFP_TYPE_CURRENT 0x0000 #endif + +#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF +#define UNICODE_BOGUS_CHAR_CODEPOINT '?' + +static uint32 utf8codepoint(const char **_str) +{ + const char *str = *_str; + uint32 retval = 0; + uint32 octet = (uint32) ((uint8) *str); + uint32 octet2, octet3, octet4; + + if (octet == 0) /* null terminator, end of string. */ + return 0; + + else if (octet < 128) /* one octet char: 0 to 127 */ + { + (*_str)++; /* skip to next possible start of codepoint. */ + return(octet); + } /* else if */ + + else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */ + { + /* + * Apparently each of these is supposed to be flagged as a bogus + * char, instead of just resyncing to the next valid codepoint. + */ + (*_str)++; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + else if (octet < 224) /* two octets */ + { + octet -= (128+64); + octet2 = (uint32) ((uint8) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 2; /* skip to next possible start of codepoint. */ + retval = ((octet << 6) | (octet2 - 128)); + if ((retval >= 0x80) && (retval <= 0x7FF)) + return retval; + } /* else if */ + + else if (octet < 240) /* three octets */ + { + octet -= (128+64+32); + octet2 = (uint32) ((uint8) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet3 = (uint32) ((uint8) *(++str)); + if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 3; /* skip to next possible start of codepoint. */ + retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) ); + + /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + switch (retval) + { + case 0xD800: + case 0xDB7F: + case 0xDB80: + case 0xDBFF: + case 0xDC00: + case 0xDF80: + case 0xDFFF: + return UNICODE_BOGUS_CHAR_VALUE; + } /* switch */ + + /* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */ + if ((retval >= 0x800) && (retval <= 0xFFFD)) + return retval; + } /* else if */ + + else if (octet < 248) /* four octets */ + { + octet -= (128+64+32+16); + octet2 = (uint32) ((uint8) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet3 = (uint32) ((uint8) *(++str)); + if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet4 = (uint32) ((uint8) *(++str)); + if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 4; /* skip to next possible start of codepoint. */ + retval = ( ((octet << 18)) | ((octet2 - 128) << 12) | + ((octet3 - 128) << 6) | ((octet4 - 128)) ); + if ((retval >= 0x10000) && (retval <= 0x10FFFF)) + return retval; + } /* else if */ + + /* + * Five and six octet sequences became illegal in rfc3629. + * We throw the codepoint away, but parse them to make sure we move + * ahead the right number of bytes and don't overflow the buffer. + */ + + else if (octet < 252) /* five octets */ + { + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 5; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + else /* six octets */ + { + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32) ((uint8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 6; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + return UNICODE_BOGUS_CHAR_VALUE; +} /* utf8codepoint */ + +void utf8ToUcs2(const char *src, uint16 *dst, uint64 len) +{ + len -= sizeof (uint16); /* save room for null char. */ + while (len >= sizeof (uint16)) + { + uint32 cp = utf8codepoint(&src); + if (cp == 0) + break; + else if (cp == UNICODE_BOGUS_CHAR_VALUE) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + + /* !!! BLUESKY: UTF-16 surrogates? */ + if (cp > 0xFFFF) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + + *(dst++) = cp; + len -= sizeof (uint16); + } /* while */ + + *dst = 0; +} /* utf8ToUcs2 */ + +static void utf8fromcodepoint(uint32 cp, char **_dst, uint64 *_len) +{ + char *dst = *_dst; + uint64 len = *_len; + + if (len == 0) + return; + + if (cp > 0x10FFFF) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */ + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + else + { + /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + switch (cp) + { + case 0xD800: + case 0xDB7F: + case 0xDB80: + case 0xDBFF: + case 0xDC00: + case 0xDF80: + case 0xDFFF: + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + } /* switch */ + } /* else */ + + /* Do the encoding... */ + if (cp < 0x80) + { + *(dst++) = (char) cp; + len--; + } /* if */ + + else if (cp < 0x800) + { + if (len < 2) + len = 0; + else + { + *(dst++) = (char) ((cp >> 6) | 128 | 64); + *(dst++) = (char) (cp & 0x3F) | 128; + len -= 2; + } /* else */ + } /* else if */ + + else if (cp < 0x10000) + { + if (len < 3) + len = 0; + else + { + *(dst++) = (char) ((cp >> 12) | 128 | 64 | 32); + *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; + *(dst++) = (char) (cp & 0x3F) | 128; + len -= 3; + } /* else */ + } /* else if */ + + else + { + if (len < 4) + len = 0; + else + { + *(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16); + *(dst++) = (char) ((cp >> 12) & 0x3F) | 128; + *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; + *(dst++) = (char) (cp & 0x3F) | 128; + len -= 4; + } /* else if */ + } /* else */ + + *_dst = dst; + *_len = len; +} /* utf8fromcodepoint */ + +#define UTF8FROMTYPE(typ, src, dst, len) \ + len--; \ + while (len) \ + { \ + const uint32 cp = (uint32) *(src++); \ + if (cp == 0) break; \ + utf8fromcodepoint(cp, &dst, &len); \ + } \ + *dst = '\0'; \ + +void utf8FromUcs2(const uint16 *src, char *dst, uint64 len) +{ + UTF8FROMTYPE(uint64, src, dst, len); +} // utf8FromUcs4 + #define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \ if (str == NULL) \ w_assignto = NULL; \ From DONOTREPLY at icculus.org Wed Sep 26 19:03:11 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 19:03:11 -0400 Subject: r361 - trunk Message-ID: <20070926230311.30838.qmail@icculus.org> Author: icculus Date: 2007-09-26 19:03:11 -0400 (Wed, 26 Sep 2007) New Revision: 361 Modified: trunk/platform_windows.c Log: Changed comments to '//' ... just cleanup here. Modified: trunk/platform_windows.c =================================================================== --- trunk/platform_windows.c 2007-09-26 22:19:35 UTC (rev 360) +++ trunk/platform_windows.c 2007-09-26 23:03:11 UTC (rev 361) @@ -15,7 +15,7 @@ // I wrote all this code under the same open source license, and own the // copyright on it anyhow, so transferring it here is "safe". -/* Forcibly disable UNICODE, since we manage this ourselves. */ +// Forcibly disable UNICODE, since we manage this ourselves. #ifdef UNICODE #undef UNICODE #endif @@ -41,21 +41,19 @@ #define LOWORDER_UINT64(pos) ((uint32) (pos & 0xFFFFFFFF)) #define HIGHORDER_UINT64(pos) ((uint32) ((pos >> 32) & 0xFFFFFFFF)) -/* - * 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. - */ +// 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... */ +// just in case... #ifndef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF #endif -/* Not defined before the Vista SDK. */ +// Not defined before the Vista SDK. #ifndef IO_REPARSE_TAG_SYMLINK #define IO_REPARSE_TAG_SYMLINK 0xA000000C #endif @@ -65,6 +63,7 @@ #define CSIDL_PERSONAL 0x0005 #endif +// This is in shlobj.h, but we can't include it due to universal.h conflicts. #ifndef SHGFP_TYPE_CURRENT #define SHGFP_TYPE_CURRENT 0x0000 #endif @@ -80,53 +79,51 @@ uint32 octet = (uint32) ((uint8) *str); uint32 octet2, octet3, octet4; - if (octet == 0) /* null terminator, end of string. */ + if (octet == 0) // null terminator, end of string. return 0; - else if (octet < 128) /* one octet char: 0 to 127 */ + else if (octet < 128) // one octet char: 0 to 127 { - (*_str)++; /* skip to next possible start of codepoint. */ + (*_str)++; // skip to next possible start of codepoint. return(octet); - } /* else if */ + } // else if - else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */ + else if ((octet > 127) && (octet < 192)) // bad (starts with 10xxxxxx). { - /* - * Apparently each of these is supposed to be flagged as a bogus - * char, instead of just resyncing to the next valid codepoint. - */ - (*_str)++; /* skip to next possible start of codepoint. */ + // Apparently each of these is supposed to be flagged as a bogus + // char, instead of just resyncing to the next valid codepoint. + (*_str)++; // skip to next possible start of codepoint. return UNICODE_BOGUS_CHAR_VALUE; - } /* else if */ + } // else if - else if (octet < 224) /* two octets */ + else if (octet < 224) // two octets { octet -= (128+64); octet2 = (uint32) ((uint8) *(++str)); - if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet2 & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; - *_str += 2; /* skip to next possible start of codepoint. */ + *_str += 2; // skip to next possible start of codepoint. retval = ((octet << 6) | (octet2 - 128)); if ((retval >= 0x80) && (retval <= 0x7FF)) return retval; - } /* else if */ + } // else if - else if (octet < 240) /* three octets */ + else if (octet < 240) // three octets { octet -= (128+64+32); octet2 = (uint32) ((uint8) *(++str)); - if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet2 & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet3 = (uint32) ((uint8) *(++str)); - if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet3 & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; - *_str += 3; /* skip to next possible start of codepoint. */ + *_str += 3; // skip to next possible start of codepoint. retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) ); - /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + // There are seven "UTF-16 surrogates" that are illegal in UTF-8. switch (retval) { case 0xD800: @@ -137,95 +134,93 @@ case 0xDF80: case 0xDFFF: return UNICODE_BOGUS_CHAR_VALUE; - } /* switch */ + } // switch - /* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */ + // 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. if ((retval >= 0x800) && (retval <= 0xFFFD)) return retval; - } /* else if */ + } // else if - else if (octet < 248) /* four octets */ + else if (octet < 248) // four octets { octet -= (128+64+32+16); octet2 = (uint32) ((uint8) *(++str)); - if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet2 & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet3 = (uint32) ((uint8) *(++str)); - if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet3 & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet4 = (uint32) ((uint8) *(++str)); - if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet4 & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; - *_str += 4; /* skip to next possible start of codepoint. */ + *_str += 4; // skip to next possible start of codepoint. retval = ( ((octet << 18)) | ((octet2 - 128) << 12) | ((octet3 - 128) << 6) | ((octet4 - 128)) ); if ((retval >= 0x10000) && (retval <= 0x10FFFF)) return retval; - } /* else if */ + } // else if - /* - * Five and six octet sequences became illegal in rfc3629. - * We throw the codepoint away, but parse them to make sure we move - * ahead the right number of bytes and don't overflow the buffer. - */ + // Five and six octet sequences became illegal in rfc3629. + // We throw the codepoint away, but parse them to make sure we move + // ahead the right number of bytes and don't overflow the buffer. - else if (octet < 252) /* five octets */ + else if (octet < 252) // five octets { octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; - *_str += 5; /* skip to next possible start of codepoint. */ + *_str += 5; // skip to next possible start of codepoint. return UNICODE_BOGUS_CHAR_VALUE; - } /* else if */ + } // else if - else /* six octets */ + else // six octets { octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; octet = (uint32) ((uint8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx? return UNICODE_BOGUS_CHAR_VALUE; - *_str += 6; /* skip to next possible start of codepoint. */ + *_str += 6; // skip to next possible start of codepoint. return UNICODE_BOGUS_CHAR_VALUE; - } /* else if */ + } // else if return UNICODE_BOGUS_CHAR_VALUE; -} /* utf8codepoint */ +} // utf8codepoint void utf8ToUcs2(const char *src, uint16 *dst, uint64 len) { - len -= sizeof (uint16); /* save room for null char. */ + len -= sizeof (uint16); // save room for null char. while (len >= sizeof (uint16)) { uint32 cp = utf8codepoint(&src); @@ -234,16 +229,16 @@ else if (cp == UNICODE_BOGUS_CHAR_VALUE) cp = UNICODE_BOGUS_CHAR_CODEPOINT; - /* !!! BLUESKY: UTF-16 surrogates? */ + // !!! FIXME: UTF-16 surrogates? if (cp > 0xFFFF) cp = UNICODE_BOGUS_CHAR_CODEPOINT; *(dst++) = cp; len -= sizeof (uint16); - } /* while */ + } // while *dst = 0; -} /* utf8ToUcs2 */ +} // utf8ToUcs2 static void utf8fromcodepoint(uint32 cp, char **_dst, uint64 *_len) { @@ -255,11 +250,11 @@ if (cp > 0x10FFFF) cp = UNICODE_BOGUS_CHAR_CODEPOINT; - else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */ + else if ((cp == 0xFFFE) || (cp == 0xFFFF)) // illegal values. cp = UNICODE_BOGUS_CHAR_CODEPOINT; else { - /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + // There are seven "UTF-16 surrogates" that are illegal in UTF-8. switch (cp) { case 0xD800: @@ -270,15 +265,15 @@ case 0xDF80: case 0xDFFF: cp = UNICODE_BOGUS_CHAR_CODEPOINT; - } /* switch */ - } /* else */ + } // switch + } // else - /* Do the encoding... */ + // Do the encoding... if (cp < 0x80) { *(dst++) = (char) cp; len--; - } /* if */ + } // if else if (cp < 0x800) { @@ -289,8 +284,8 @@ *(dst++) = (char) ((cp >> 6) | 128 | 64); *(dst++) = (char) (cp & 0x3F) | 128; len -= 2; - } /* else */ - } /* else if */ + } // else + } // else if else if (cp < 0x10000) { @@ -302,8 +297,8 @@ *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; *(dst++) = (char) (cp & 0x3F) | 128; len -= 3; - } /* else */ - } /* else if */ + } // else + } // else if else { @@ -316,12 +311,12 @@ *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; *(dst++) = (char) (cp & 0x3F) | 128; len -= 4; - } /* else if */ - } /* else */ + } // else if + } // else *_dst = dst; *_len = len; -} /* utf8fromcodepoint */ +} // utf8fromcodepoint #define UTF8FROMTYPE(typ, src, dst, len) \ len--; \ @@ -385,12 +380,12 @@ retval = (char *) xmalloc(len * 4); utf8FromUcs2(wbuf, retval, len * 4); smallFree(wbuf); - } /* if */ + } // if return(retval); -} /* codepageToUtf8Heap */ +} // codepageToUtf8Heap -/* pointers for APIs that may not exist on some Windows versions... */ +// pointers for APIs that may not exist on some Windows versions... static HANDLE libKernel32 = NULL; static HANDLE libUserEnv = NULL; static HANDLE libAdvApi32 = NULL; @@ -417,14 +412,13 @@ static BOOL (WINAPI *pMoveFileW)(LPCWSTR, LPCWSTR); static void (WINAPI *pOutputDebugStringW)(LPCWSTR); -/* - * Fallbacks for missing Unicode functions on Win95/98/ME. These are filled - * into the function pointers if looking up the real Unicode entry points - * in the system DLLs fails, so they're never used on WinNT/XP/Vista/etc. - * They make an earnest effort to convert to/from UTF-8 and UCS-2 to - * the user's current codepage. - */ +// Fallbacks for missing Unicode functions on Win95/98/ME. These are filled +// into the function pointers if looking up the real Unicode entry points +// in the system DLLs fails, so they're never used on WinNT/XP/Vista/etc. +// They make an earnest effort to convert to/from UTF-8 and UCS-2 to +// the user's current codepage. + static BOOL WINAPI fallbackGetUserNameW(LPWSTR buf, LPDWORD len) { const DWORD cplen = *len; @@ -434,7 +428,7 @@ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, cplen, buf, *len); smallFree(cpstr); return(retval); -} /* fallbackGetUserNameW */ +} // fallbackGetUserNameW static DWORD WINAPI fallbackFormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLangId, @@ -448,7 +442,7 @@ MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize); smallFree(cpbuf); return(retval); -} /* fallbackFormatMessageW */ +} // fallbackFormatMessageW static DWORD WINAPI fallbackGetModuleFileNameW(HMODULE hMod, LPWCH lpBuf, DWORD nSize) @@ -459,7 +453,7 @@ MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize); smallFree(cpbuf); return(retval); -} /* fallbackGetModuleFileNameW */ +} // fallbackGetModuleFileNameW static DWORD WINAPI fallbackGetFileAttributesW(LPCWSTR fname) { @@ -470,7 +464,7 @@ retval = GetFileAttributesA(cpstr); smallFree(cpstr); return(retval); -} /* fallbackGetFileAttributesW */ +} // fallbackGetFileAttributesW static DWORD WINAPI fallbackGetCurrentDirectoryW(DWORD buflen, LPWSTR buf) { @@ -483,9 +477,9 @@ { MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,buf,buflen); smallFree(cpbuf); - } /* if */ - return(retval); -} /* fallbackGetCurrentDirectoryW */ + } // if + return retval; +} // fallbackGetCurrentDirectoryW static BOOL WINAPI fallbackRemoveDirectoryW(LPCWSTR dname) { @@ -496,7 +490,7 @@ retval = RemoveDirectoryA(cpstr); smallFree(cpstr); return(retval); -} /* fallbackRemoveDirectoryW */ +} // fallbackRemoveDirectoryW static BOOL WINAPI fallbackCreateDirectoryW(LPCWSTR dname, LPSECURITY_ATTRIBUTES attr) @@ -508,7 +502,7 @@ retval = CreateDirectoryA(cpstr, attr); smallFree(cpstr); return(retval); -} /* fallbackCreateDirectoryW */ +} // fallbackCreateDirectoryW static BOOL WINAPI fallbackDeleteFileW(LPCWSTR fname) { @@ -519,7 +513,7 @@ retval = DeleteFileA(cpstr); smallFree(cpstr); return(retval); -} /* fallbackDeleteFileW */ +} // fallbackDeleteFileW static HANDLE WINAPI fallbackCreateFileW(LPCWSTR fname, DWORD dwDesiredAccess, DWORD dwShareMode, @@ -535,7 +529,7 @@ dwCreationDisposition, dwFlagsAndAttrs, hTemplFile); smallFree(cpstr); return(retval); -} /* fallbackCreateFileW */ +} // fallbackCreateFileW static BOOL WINAPI fallbackMoveFileW(LPCWSTR src, LPCWSTR dst) { @@ -550,7 +544,7 @@ smallFree(srccpstr); smallFree(dstcpstr); return(retval); -} /* fallbackMoveFileW */ +} // fallbackMoveFileW static void WINAPI fallbackOutputDebugStringW(LPCWSTR str) { @@ -562,11 +556,11 @@ } // fallbackOutputDebugStringW -/* A blatant abuse of pointer casting... */ +// A blatant abuse of pointer casting... static int symLookup(HMODULE dll, void **addr, const char *sym) { return( (*addr = GetProcAddress(dll, sym)) != NULL ); -} /* symLookup */ +} // symLookup static int findApiSymbols(void) @@ -586,19 +580,19 @@ p##x = fallback##x; \ } - /* Apparently Win9x HAS the Unicode entry points, they just don't WORK. */ - /* ...so don't look them up unless we're on NT+. (see osHasUnicode.) */ + // Apparently Win9x HAS the Unicode entry points, they just don't WORK. + // ...so don't look them up unless we're on NT+. (see osHasUnicode.) dll = libUserEnv = LoadLibraryA("userenv.dll"); if (dll != NULL) LOOKUP_NOFALLBACK(GetUserProfileDirectoryW, osHasUnicode); - /* !!! FIXME: what do they call advapi32.dll on Win64? */ + // !!! FIXME: what do they call advapi32.dll on Win64? dll = libAdvApi32 = LoadLibraryA("advapi32.dll"); if (dll != NULL) LOOKUP(GetUserNameW, osHasUnicode); - /* !!! FIXME: what do they call kernel32.dll on Win64? */ + // !!! FIXME: what do they call kernel32.dll on Win64? dll = libKernel32 = LoadLibraryA("kernel32.dll"); if (dll != NULL) { @@ -616,9 +610,9 @@ LOOKUP(DeleteFileW, osHasUnicode); LOOKUP(MoveFileW, osHasUnicode); LOOKUP(OutputDebugStringW, osHasUnicode); - } /* if */ + } // if - /* !!! FIXME: what do they call shell32.dll on Win64? */ + // !!! FIXME: what do they call shell32.dll on Win64? dll = libShell32 = LoadLibraryA("shell32.dll"); if (dll != NULL) LOOKUP_NOFALLBACK(SHGetFolderPathA, 1); @@ -627,7 +621,7 @@ #undef LOOKUP return(1); -} /* findApiSymbols */ +} // findApiSymbols @@ -645,12 +639,12 @@ pGetCurrentDirectoryW(buflen, wbuf); if (wbuf[buflen - 2] == '\\') - wbuf[buflen - 1] = '\0'; /* just in case... */ + wbuf[buflen - 1] = '\0'; // just in case... else { wbuf[buflen - 1] = '\\'; wbuf[buflen] = '\0'; - } /* else */ + } // else retval = unicodeToUtf8Heap(wbuf); smallFree(wbuf); @@ -681,10 +675,8 @@ retval = (char *) xmalloc(MAX_PATH); - /* - * If in \\server\path format, it's already an absolute path. - * We'll need to check for "." and ".." dirs, though, just in case. - */ + // 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); @@ -697,7 +689,7 @@ return NULL; } // if - if (path[1] == ':') /* drive letter specified? */ + 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 @@ -711,7 +703,7 @@ { strcpy(retval, currentDir); strcat(retval, path + 2); - } /* if */ + } // if else // not current drive; absolute. { @@ -730,7 +722,7 @@ retval[0] = currentDir[0]; retval[1] = ':'; strcpy(retval + 2, path); - } /* if */ + } // if else { strcpy(retval, currentDir); @@ -1083,12 +1075,11 @@ boolean MojoPlatform_issymlink(const char *fname) { - /* !!! FIXME: - * Windows Vista can have NTFS symlinks. Can older Windows releases have - * them when talking to a network file server? What happens when you - * mount a NTFS partition on XP that was plugged into a Vista install - * that made a symlink? - */ + // !!! FIXME: + // Windows Vista can have NTFS symlinks. Can older Windows releases have + // them when talking to a network file server? What happens when you + // mount a NTFS partition on XP that was plugged into a Vista install + // that made a symlink? boolean retval = false; LPWSTR wpath; From DONOTREPLY at icculus.org Wed Sep 26 19:09:37 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 19:09:37 -0400 Subject: r362 - trunk Message-ID: <20070926230937.1539.qmail@icculus.org> Author: icculus Date: 2007-09-26 19:09:37 -0400 (Wed, 26 Sep 2007) New Revision: 362 Modified: trunk/platform_windows.c Log: A little more Ryanification. Modified: trunk/platform_windows.c =================================================================== --- trunk/platform_windows.c 2007-09-26 23:03:11 UTC (rev 361) +++ trunk/platform_windows.c 2007-09-26 23:09:37 UTC (rev 362) @@ -85,7 +85,7 @@ else if (octet < 128) // one octet char: 0 to 127 { (*_str)++; // skip to next possible start of codepoint. - return(octet); + return octet; } // else if else if ((octet > 127) && (octet < 192)) // bad (starts with 10xxxxxx). @@ -349,7 +349,7 @@ uint32 len = 0; while (*(wstr++)) len++; - return(len); + return len; } // wStrLen @@ -364,7 +364,7 @@ utf8FromUcs2((const uint16 *) w_str, retval, len); retval = xrealloc(retval, strlen(retval) + 1); // shrink. } // if - return(retval); + return retval; } // unicodeToUtf8Heap @@ -381,7 +381,7 @@ utf8FromUcs2(wbuf, retval, len * 4); smallFree(wbuf); } // if - return(retval); + return retval; } // codepageToUtf8Heap @@ -427,7 +427,7 @@ if (buf != NULL) MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, cplen, buf, *len); smallFree(cpstr); - return(retval); + return retval; } // fallbackGetUserNameW static DWORD WINAPI fallbackFormatMessageW(DWORD dwFlags, LPCVOID lpSource, @@ -441,7 +441,7 @@ if (retval > 0) MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize); smallFree(cpbuf); - return(retval); + return retval; } // fallbackFormatMessageW static DWORD WINAPI fallbackGetModuleFileNameW(HMODULE hMod, LPWCH lpBuf, @@ -452,7 +452,7 @@ if (retval > 0) MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize); smallFree(cpbuf); - return(retval); + return retval; } // fallbackGetModuleFileNameW static DWORD WINAPI fallbackGetFileAttributesW(LPCWSTR fname) @@ -463,7 +463,7 @@ WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL); retval = GetFileAttributesA(cpstr); smallFree(cpstr); - return(retval); + return retval; } // fallbackGetFileAttributesW static DWORD WINAPI fallbackGetCurrentDirectoryW(DWORD buflen, LPWSTR buf) @@ -489,7 +489,7 @@ WideCharToMultiByte(CP_ACP, 0, dname, buflen, cpstr, buflen, NULL, NULL); retval = RemoveDirectoryA(cpstr); smallFree(cpstr); - return(retval); + return retval; } // fallbackRemoveDirectoryW static BOOL WINAPI fallbackCreateDirectoryW(LPCWSTR dname, @@ -501,7 +501,7 @@ WideCharToMultiByte(CP_ACP, 0, dname, buflen, cpstr, buflen, NULL, NULL); retval = CreateDirectoryA(cpstr, attr); smallFree(cpstr); - return(retval); + return retval; } // fallbackCreateDirectoryW static BOOL WINAPI fallbackDeleteFileW(LPCWSTR fname) @@ -512,7 +512,7 @@ WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL); retval = DeleteFileA(cpstr); smallFree(cpstr); - return(retval); + return retval; } // fallbackDeleteFileW static HANDLE WINAPI fallbackCreateFileW(LPCWSTR fname, @@ -528,7 +528,7 @@ retval = CreateFileA(cpstr, dwDesiredAccess, dwShareMode, lpSecurityAttrs, dwCreationDisposition, dwFlagsAndAttrs, hTemplFile); smallFree(cpstr); - return(retval); + return retval; } // fallbackCreateFileW static BOOL WINAPI fallbackMoveFileW(LPCWSTR src, LPCWSTR dst) @@ -543,7 +543,7 @@ retval = MoveFileA(srccpstr, dstcpstr); smallFree(srccpstr); smallFree(dstcpstr); - return(retval); + return retval; } // fallbackMoveFileW static void WINAPI fallbackOutputDebugStringW(LPCWSTR str) @@ -559,11 +559,11 @@ // A blatant abuse of pointer casting... static int symLookup(HMODULE dll, void **addr, const char *sym) { - return( (*addr = GetProcAddress(dll, sym)) != NULL ); + return ((*addr = GetProcAddress(dll, sym)) != NULL); } // symLookup -static int findApiSymbols(void) +static boolean findApiSymbols(void) { const boolean osHasUnicode = !osIsWin9x; HMODULE dll = NULL; @@ -620,7 +620,7 @@ #undef LOOKUP_NOFALLBACK #undef LOOKUP - return(1); + return true; } // findApiSymbols @@ -648,7 +648,7 @@ retval = unicodeToUtf8Heap(wbuf); smallFree(wbuf); - return(retval); + return retval; } // MojoPlatform_currentWorkingDir @@ -773,7 +773,7 @@ } // while // shrink the retval's memory block if possible... - return((char *) xrealloc(retval, strlen(retval) + 1)); + return (char *) xrealloc(retval, strlen(retval) + 1); } // MojoPlatform_realpath @@ -824,7 +824,7 @@ } // else free(modpath); - return(retval); + return retval; } // MojoPlatform_appBinaryPath From DONOTREPLY at icculus.org Wed Sep 26 22:50:33 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 22:50:33 -0400 Subject: r363 - trunk Message-ID: <20070927025033.25459.qmail@icculus.org> Author: icculus Date: 2007-09-26 22:50:32 -0400 (Wed, 26 Sep 2007) New Revision: 363 Modified: trunk/CMakeLists.txt Log: Should fix linking issues on Windows...? Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2007-09-26 23:09:37 UTC (rev 362) +++ trunk/CMakeLists.txt 2007-09-27 02:50:32 UTC (rev 363) @@ -43,6 +43,7 @@ IF(WINDOWS) ADD_DEFINITIONS(-DPLATFORM_WINDOWS=1) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1) + SET(USES_WINMAIN WIN32) ENDIF(WINDOWS) IF(MACOSX) @@ -552,7 +553,7 @@ ADD_CUSTOM_TARGET(lua "${MOJOLUAC_LOCATION}" -p ${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.lua) ENDIF(MOJOSETUP_BUILD_LUAC) -ADD_EXECUTABLE(mojosetup ${MOJOSETUP_SRCS} ${OPTIONAL_SRCS}) +ADD_EXECUTABLE(mojosetup ${USES_WINMAIN} ${MOJOSETUP_SRCS} ${OPTIONAL_SRCS}) GET_TARGET_PROPERTY(MOJOSETUP_BINARY_LOCATION mojosetup LOCATION) TARGET_LINK_LIBRARIES(mojosetup ${OPTIONAL_LIBS}) SET(MOJOSETUP_TARGETS "${MOJOSETUP_TARGETS};mojosetup") From DONOTREPLY at icculus.org Wed Sep 26 23:00:40 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 23:00:40 -0400 Subject: r364 - trunk Message-ID: <20070927030040.30247.qmail@icculus.org> Author: icculus Date: 2007-09-26 23:00:40 -0400 (Wed, 26 Sep 2007) New Revision: 364 Modified: trunk/mojosetup.c Log: Don't crash if panic() when there's no initialized GUI layer. Modified: trunk/mojosetup.c =================================================================== --- trunk/mojosetup.c 2007-09-27 02:50:32 UTC (rev 363) +++ trunk/mojosetup.c 2007-09-27 03:00:40 UTC (rev 364) @@ -488,7 +488,7 @@ if (domsgbox) GGui->msgbox(_("PANIC"), err); - if (GGui->deinit != NULL) + if ((GGui != NULL) && (GGui->deinit != NULL)) GGui->deinit(); if (!domsgbox) From DONOTREPLY at icculus.org Wed Sep 26 23:01:39 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 26 Sep 2007 23:01:39 -0400 Subject: r365 - trunk Message-ID: <20070927030139.30681.qmail@icculus.org> Author: icculus Date: 2007-09-26 23:01:39 -0400 (Wed, 26 Sep 2007) New Revision: 365 Modified: trunk/platform_windows.c Log: Add endlines to OutputDebugString() text. Modified: trunk/platform_windows.c =================================================================== --- trunk/platform_windows.c 2007-09-27 03:00:40 UTC (rev 364) +++ trunk/platform_windows.c 2007-09-27 03:01:39 UTC (rev 365) @@ -1477,10 +1477,12 @@ { if (pOutputDebugStringW != NULL) // in case this gets called before init... { + static const WCHAR endl[3] = { '\r', '\n', '\0' }; WCHAR *wstr; UTF8_TO_UNICODE_STACK_MACRO(wstr, str); STUBBED("OutputDebugString() is probably not best here"); pOutputDebugStringW(wstr); + pOutputDebugStringW(endl); smallFree(wstr); } // if } // MojoPlatform_log From DONOTREPLY at icculus.org Sat Sep 29 21:44:31 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 29 Sep 2007 21:44:31 -0400 Subject: r366 - trunk Message-ID: <20070930014431.31460.qmail@icculus.org> Author: icculus Date: 2007-09-29 21:44:31 -0400 (Sat, 29 Sep 2007) New Revision: 366 Modified: trunk/docs.txt Log: Some documentation updates. Modified: trunk/docs.txt =================================================================== --- trunk/docs.txt 2007-09-27 03:01:39 UTC (rev 365) +++ trunk/docs.txt 2007-09-30 01:44:31 UTC (rev 366) @@ -864,17 +864,21 @@ and "YY" is the country code: "en_US" for American English, fr_CA for French Canadian, etc. + If MojoSetup can't determine the user's locale, this string is "???". + MojoSetup.info.platform This is a string (not a function!) of the current platform. This is - currently one of "macosx", "unix", "windows", or "beos". + currently one of "macosx", "unix", "windows", or "beos", or one of several + others, depending on your build and target platform. MojoSetup.info.arch This is a string (not a function!) of the current platform's CPU type. - This is currently one of "x86", "x86-64", "powerpc", or "powerpc64". + This is currently one of "x86", "x86-64", "powerpc", "powerpc64", + or one of several others, depending on your build and target platform. Please note that this is the arch of the installer binary...you can run a 32-bit binary on an amd64 chip, in which case it will report "x86"! @@ -888,9 +892,14 @@ Please note that this is the OS target of the installer binary...you can run a Linux binary on FreeBSD through the binary compatibility layer, - in which case it will report "linux"! + in which case it will still report "linux"! + On Windows, this is currently either "win9x" or "winnt" to differentiate + Windows 95/98/ME from NT/XP/Vista/etc, since their version numbers can + overlap. Installers should not rely on there never being a third string + some day in the distant future, though. + MojoSetup.info.osversion This is a string (not a function!) of the current platform's operating @@ -902,11 +911,33 @@ gives you the kernel version, which is usually not helpful, but could be on, say, BeOS. + On Windows, it'll be the Major.Minor.Build version for the OS. This is the + same information that the win32 OSVERSIONINFO structure supplies: + http://msdn2.microsoft.com/en-us/library/ms724834.aspx + + So "5.1.2600" might mean "Windows XP, service pack 1" ... relying on the + build number can be very dangerous if you don't know what you're doing, + but the major/minor values appear to be reliable to differentiate various + flavors of Windows (and MojoSetup.info.ostype can differentiate between + the Win95-based and WinNT-based versions). + + On any platform, it would be wise to not rely too heavily on this data: + it's frequently better to check for the specific thing you want to know + about ("Is DirectX 9 installed?") rather than ask a general question ("Is + this Windows XP?"). This prevents problems when unexpected values arise in + situations you never expected to handle (for example, if you ran the + Windows installer under Wine, it could report that its Windows XP, but + there's no DirectX 9 support). Knowing what you really want to know is + half the battle. + + MojoSetup.info.ui This is a string (not a function!) of the UI plugin that MojoSetup chose. - system. This is currently one of "stdio", "macosx", or "gtkplus2". + system. This is currently one of "stdio", "ncurses", "macosx", "gtkplus2", + or one of several others, depending on your build and target platform. + It's best to not rely on this being within a specific set of values. MojoSetup.info.buildver From DONOTREPLY at icculus.org Sat Sep 29 22:08:29 2007 From: DONOTREPLY at icculus.org (DONOTREPLY at icculus.org) Date: 29 Sep 2007 22:08:29 -0400 Subject: r367 - trunk Message-ID: <20070930020829.14198.qmail@icculus.org> Author: icculus Date: 2007-09-29 22:08:29 -0400 (Sat, 29 Sep 2007) New Revision: 367 Modified: trunk/fileio.c Log: Don't dereference a NULL pointer right before we check if it's actually NULL. Thanks to Gerry JJ for the catch. Modified: trunk/fileio.c =================================================================== --- trunk/fileio.c 2007-09-30 01:44:31 UTC (rev 366) +++ trunk/fileio.c 2007-09-30 02:08:29 UTC (rev 367) @@ -348,13 +348,15 @@ char *fullpath = NULL; char *dent = NULL; // "dent" == "directory entry" MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque; - const char *basepath = inst->dirs->basepath; + const char *basepath; MojoArchive_resetEntry(&ar->prevEnum); if (inst->dirs == NULL) return NULL; + basepath = inst->dirs->basepath; + // if readdir fails, it's end of dir (!!! FIXME: what about i/o failures?) dent = MojoPlatform_readdir(inst->dirs->dir); if (dent == NULL) // end of dir?