diff --git a/ANNOUNCE b/ANNOUNCE index 86723e9ff15..703bde4ed4c 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,13 +1,13 @@ -This is release 951226 of Wine the MS Windows emulator. This is still a +This is release 960114 of Wine the MS Windows emulator. This is still a developer's only release. There are many bugs and many unimplemented API features. Most applications still do not work. Patches should be submitted to "wine-new@amscons.com". Please don't forget to include a ChangeLog entry. I'll make a new release every other week. -WHAT'S NEW with Wine-951226: (see ChangeLog for details) - - Many more Winelib fixes. - - Language is now a run-time option. +WHAT'S NEW with Wine-960114: (see ChangeLog for details) + - Complete rewrite of the file handling; still has a few bugs. + - Tons of new Win32 code. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -16,10 +16,10 @@ Because of lags created by using mirror, this message may reach you before the release is available at the ftp sites. The sources will be available from the following locations: - sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-951226.tar.gz - tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-951226.tar.gz - ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-951226.tar.gz - aris.com:/pub/linux/ALPHA/Wine/development/Wine-951226.tar.gz + sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-960114.tar.gz + tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960114.tar.gz + ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960114.tar.gz + aris.com:/pub/linux/ALPHA/Wine/development/Wine-960114.tar.gz It should also be available from any site that mirrors tsx-11 or sunsite. diff --git a/ChangeLog b/ChangeLog index fc9e70be8d7..d7a84c28048 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,205 @@ +---------------------------------------------------------------------- +Sun Jan 14 13:45:22 1996 Alexandre Julliard + + * [configure.in] + Added check for gcc strength-reduce bug. + + * [controls/listbox.c] + Changed ListBoxDirectory() to use the new DOS file functions. + + * [controls/menu.c] + Fixed parameters for DeleteMenu() call in ChangeMenu(). + + * [debugger/stack.c] + Also display current frame in back-trace. + + * [files/directory.c] [files/dos_fs.c] [files/drive.c] [files/file.c] + Complete rewrite of the DOS file handling. + Implemented per-task file handles. + Removed default Z: drive; needs to be put explicitely in wine.ini + if desired. + + * [loader/module.c] + Fixed file descriptor leak in LoadModule(). + + * [loader/task.c] + Initialise PDB file handle table in TASK_CreateTask(). + Close file handles on task termination. + Implemented SetErrorMode(). + + * [misc/network.c] + Fixed WNetGetConnection() to use GetDriveType(). + + * [misc/xmalloc.c] + Added function xstrdup(). + + * [miscemu/int21.c] + Many changes for new DOS file functions. + + * [miscemu/interrupts.c] + Moved DOS_GetEquipment() function into INT_Int11Handler(). + + * [windows/win.c] + Bug fix: create system menu before sending WM_NCCREATE. + + * [*/*.c] + Replaced strcasecmp and strncasecmp by lstrcmpi and lstrncmpi for + better portability. + +Sat Jan 13 16:13:02 1996 Jim Peterson + + * [include/wintypes.h] + Added 'typedef HGLOBAL GOBALHANDLE;'. This is not precisely in line + with the true windows 'typedef HANDLE GLOBALHANDLE;', but I believe + it should suffice. + + * [include/winsock.h] + Added '#include ' for various declarations. '#ifdef'-ed + out some old style internet address #define's. + + * [loader/task.c] + Made MakeProcInstance() return first parameter #ifdef WINELIB32. + Made FreeProcInstance() do nothing #ifdef WINELIB32. + '#ifdef'-ed out TASK_AllocThunk(), as it was unused in WINELIB32. + + * [library/miscstubs.c] + Made GetWndProcEntry16() return ACTIVATEAPP_callback() when called + with name="ActivateAppProc". This hardly seems correct, but it's my + best guess as to how the emulator responds. + +Sat Jan 6 17:57:45 1996 Martin von Loewis + + * [if1632/kernel32.spec][win32/process.c] + WIN32_GetProcAddress, LoadLibraryA: new functions + + * [if1632/relay32.c] + RELAY32_GetEntryPoint: Removed code to load PE DLLs + + * [include/pe_image.h][include/pe_exe.h] + struct pe_data: new fields base_addr,load_addr,vma_size,pe_reloc + struct PE_Reloc_Block: new structure + + * [loader/module.c] + MODULE_RegisterModule: new function + + * [loader/pe_image.c] + PE_FindExportedFunction,PE_GetProcAddress: new functions + fixup_imports: expect struct w_files* now, fill dlls_to_init, + load PE DLLs + do_relocations: new functions + calc_vma_size: renamed from dump_table + PE_LoadImage: use malloc to allocate memory for image + PE_InitDLL: expect HMODULE + PE_InitializeDLLs: new function + + * [loader/task.c] + NE_InitializeDLLs: branch to PE_InitializeDLLs for PE modules + GetExePtr: Accept PE modules + + * [misc/commdlg.c] + FILEDLG_WMCommand: unpack WIN32 WM_COMMAND appropriately for WineLib + +Thu Jan 4 11:36:21 1996 Manfred Weichel + + * [misc/port.c] + New file with usleep() function for SVR4. + + * [configure.in] + Check for usleep() function. + +Tue Jan 02 14:00:00 1996 Anand Kumria + + * [if1632/toolhelp.spec] [include/toolhelp.h] + [misc/user.c] [windows/message.c] + Implement TOOLHELP.80 TimerCount. Fix GetTickCount. + + * [miscemu/dpmi.c] + Implement DPMI Get Page Size (AX=0604, INT 31) + + * [memory/global.c] + Implement TOOLHELP.72 GetMemManInfo. + +Mon Jan 2 10:33:00 1996 Thomas Sandford + + * [if1632/callback.c] + CallWindowProc() - When calling RELAY32_CallWindowProc, check + whether lParam should be a SEGPTR, and if so convert it to one. + + * [if1632/gdi.spec] [if1632/kernel32.spec] [if1632/user32.spec] + Numerous functions added, mostly calls to original (win16) + functions. Note that some (many) of these are probably not + strictly correct, but with these additions freecell will at least + display its main window though it is garbled. + + * [if1632/winprocs.spec] + Completely rewritten - all WndProcs now have win32 versions to + help with the lparam SEGPTR fix in callback.c + + * [include/kernel32.h] + LPTCSTR defined. + + * [include/peexe.h] + Definition of PE_Export_Directory amended. + + * [include/resource32.h] + New file. + + * [include/stackframe.h] + Definition of MAKE_SEGPTR macro #ifdef'd out and replaced with + prototype for replacement function in memory/selector.c which + can operate on any given memory address. This is currently + required for win32 support. It is a dreadful cludge, and will + certainly slow down other programs. If you are not interested + in win32 development you may wish to reverse this patch. + + * [include/windows.h] + Definition of SW_SHOWDEFAULT added. + + * [loader/pe_image.c] + Extensive rewrites of xmmap() fixup_imports(). + PE_LoadImage() - initialisation of bss added, extraction of + module name fixed, initialisation of DLL added. + PE_InitDLL() - now does something. + PE_Win32CallToStart() - initialisation of TEB pointed to by + fs added. + PE_InitTEB() created to perform TEB initialisation. + + * [memory/selector.c] + New function MAKE_SEGPTR() - see include/stackframe.h above. + + * [misc/user32.c] + USER32_RegisterClassA(), CreateWindowExA() memory allocation + method changed. This is probably now unnecessary with the + new MAKE_SEGPTR handling code. + USER32_DefWndProcA() removed to win32/winprocs.c + USER32_TranslateMessage added. + + * [tools/build.c] + handling of win32 spec files changed to support gcc2.6.X + this requires optimisations to be disabled. + + * [win32/resource.c] [win32/newfns.c] [win32/heap.c] [win32/winprocs.c] + New files. + + * [win32/Makefile.in] + New files heap.c, newfns.c, resource.c and winprocs.c added to build. + + * [win32/file.c] + New function W32_SetHandleCount. + + * [win32/init.c] + WIN32_GetModuleHandle() - now returns handle of running process + if called with NULL. + GetStartupInfoA() - set cbReserved2 to 0. + + * [win32/memory.c] + VirtualAlloc() - set mmap() file parameter to -1 instead of 0 to make + it work with FreeBSD. Also check for return value. Removed extra + return. + + * [windows/winpos.c] + ShowWindow() - SW_SHOWDEFAULT handling kludged in. + ---------------------------------------------------------------------- Sat Dec 23 18:15:59 1995 Alexandre Julliard diff --git a/Makefile.in b/Makefile.in index faea81911fe..0e3459b9112 100644 --- a/Makefile.in +++ b/Makefile.in @@ -49,6 +49,7 @@ MAIN_TARGET = @MAIN_TARGET@ COMMONSUBDIRS = \ rc \ controls \ + files \ ipc \ loader \ misc \ @@ -72,6 +73,7 @@ ALLSUBDIRS = $(COMMONSUBDIRS) $(EMUSUBDIRS) $(LIBSUBDIRS) libtest COMMONOBJS = \ controls/controls.o \ + files/files.o \ ipc/ipc.o \ loader/loader.o \ misc/misc.o \ diff --git a/configure b/configure index 704cc35a345..0689562737d 100755 --- a/configure +++ b/configure @@ -685,7 +685,6 @@ else test "${CFLAGS+set}" = set || CFLAGS="-g" fi -test "x${GCC}" = "xyes" && CFLAGS="$CFLAGS -Wall -fno-strength-reduce" echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then @@ -701,7 +700,7 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error @@ -715,7 +714,7 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error @@ -821,7 +820,7 @@ test -z "$x_direct_test_library" && x_direct_test_library=Xt test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h cat > conftest.$ac_ext < EOF @@ -884,7 +883,7 @@ rm -f conftest* ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&6 +if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_cross=yes +else +cat > conftest.$ac_ext </dev/null; then + ac_cv_c_cross=no +else + ac_cv_c_cross=yes +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ac_cv_c_cross" 1>&6 +cross_compiling=$ac_cv_c_cross + + echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_gcc_strength_bug="yes" +else +cat > conftest.$ac_ext </dev/null; then + ac_cv_c_gcc_strength_bug="no" +else + ac_cv_c_gcc_strength_bug="yes" +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ac_cv_c_gcc_strength_bug" 1>&6 + if test "$ac_cv_c_gcc_strength_bug" = "yes" + then + CFLAGS="$CFLAGS -fno-strength-reduce" + fi +fi + + +for ac_func in tcgetattr usleep do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 else cat > conftest.$ac_ext < EOF @@ -1509,7 +1574,7 @@ if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1564,7 +1629,7 @@ if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 -if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_c_cross=yes -else -cat > conftest.$ac_ext </dev/null; then - ac_cv_c_cross=no -else - ac_cv_c_cross=yes -fi -fi -rm -fr conftest* -fi - -echo "$ac_t""$ac_cv_c_cross" 1>&6 -cross_compiling=$ac_cv_c_cross - echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1686,7 +1725,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1704,7 +1743,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1725,7 +1764,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1760,7 +1799,7 @@ if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -1896,6 +1935,7 @@ Makefile controls/Makefile debugger/Makefile debugger/readline/Makefile +files/Makefile if1632/Makefile ipc/Makefile library/Makefile @@ -1967,6 +2007,7 @@ Makefile controls/Makefile debugger/Makefile debugger/readline/Makefile +files/Makefile if1632/Makefile ipc/Makefile library/Makefile diff --git a/configure.in b/configure.in index 27490d1f892..d8a94c0254d 100644 --- a/configure.in +++ b/configure.in @@ -29,8 +29,6 @@ dnl **** Check for some programs and libraries **** AC_PROG_MAKE_SET AC_PROG_CC -dnl Add some options for gcc -test "x${GCC}" = "xyes" && CFLAGS="$CFLAGS -Wall -fno-strength-reduce" AC_PROG_CPP AC_PATH_XTRA AC_PROG_YACC @@ -40,9 +38,33 @@ AC_PROG_INSTALL dnl Check for -li386 for NetBSD AC_CHECK_LIB(i386,i386_set_ldt,LDLIBS="$LDLIBS -li386") +dnl **** Check for gcc strength-reduce bug **** + +if test "x${GCC}" = "xyes" +then + CFLAGS="$CFLAGS -Wall" + AC_C_CROSS + AC_CACHE_CHECK( "for gcc strength-reduce bug", ac_cv_c_gcc_strength_bug, + AC_TRY_RUN([ +int main(void) { + static int Array[3]; + unsigned int B = 3; + int i; + for(i=0; i= 0); + } + if (idStatic) + { + char temp[256]; + int drive = DRIVE_GetCurrentDrive(); + strcpy( temp, "A:\\" ); + temp[0] += drive; + lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 ); + SendDlgItemMessage( hDlg, idStatic, WM_SETTEXT, + 0, (LPARAM)MAKE_SEGPTR(temp) ); + } + return ret; } diff --git a/controls/desktop.c b/controls/desktop.c index b3796f493db..9f462c6e583 100644 --- a/controls/desktop.c +++ b/controls/desktop.c @@ -22,18 +22,19 @@ static char Copyright[] = "Copyright Alexandre Julliard, 1994"; * * Load a bitmap from a file. Used by SetDeskWallPaper(). */ -static HBITMAP DESKTOP_LoadBitmap( HDC hdc, char *filename ) +static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename ) { BITMAPFILEHEADER *fileHeader; BITMAPINFO *bitmapInfo; HBITMAP hbitmap; - char *unixFileName, *buffer; + char *buffer; + const char *unixFileName; int file; long size; /* Read all the file into memory */ - if (!(unixFileName = DOS_GetUnixFileName( filename ))) return 0; + if (!(unixFileName = DOSFS_GetUnixFileName( filename, TRUE ))) return 0; if ((file = open( unixFileName, O_RDONLY )) == -1) return 0; size = lseek( file, 0, SEEK_END ); if (!(buffer = (char *)malloc( size ))) @@ -159,7 +160,7 @@ BOOL SetDeskPattern(void) /*********************************************************************** * SetDeskWallPaper (USER.285) */ -BOOL SetDeskWallPaper( LPSTR filename ) +BOOL SetDeskWallPaper( LPCSTR filename ) { HBITMAP hbitmap; HDC hdc; diff --git a/controls/listbox.c b/controls/listbox.c index d1b0df79207..7ecd806afc8 100644 --- a/controls/listbox.c +++ b/controls/listbox.c @@ -24,6 +24,8 @@ #include "msdos.h" #include "listbox.h" #include "dos_fs.h" +#include "drive.h" +#include "stackframe.h" #include "stddebug.h" #include "debug.h" #include "xmalloc.h" @@ -633,65 +635,79 @@ int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex) int ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPSTR filespec) { - struct dosdirent *dp, *dp_old; - char temp[256]; - int drive; - LPSTR tstr; + const char *pathPtr, *maskPtr; + char mask[12], path[MAX_PATHNAME_LEN]; + int skip, count; + DOS_DIRENT entry; + + char temp[256]; + int drive; + LPSTR tstr; dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib); if (strchr(filespec, '\\') || strchr(filespec, ':')) { - drive = DOS_GetDefaultDrive(); if (filespec[1] == ':') { drive = toupper(filespec[0]) - 'A'; filespec += 2; } + else drive = DRIVE_GetCurrentDrive(); strcpy(temp,filespec); tstr = strrchr(temp, '\\'); if (tstr != NULL) { *(tstr+1) = 0; filespec += tstr - temp + 1; - if (!DOS_ChangeDir( drive, temp )) return 0; + if (!DRIVE_Chdir( drive, temp )) return 0; } - DOS_SetDefaultDrive( drive ); + DRIVE_SetCurrentDrive( drive ); dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n", drive+'A', temp, filespec); } - if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0; - dp_old = dp; - while ((dp = (struct dosdirent *)DOS_readdir(dp))) { - if (!dp->inuse) break; - dprintf_listbox(stddeb, "ListBoxDirectory %p '%s' !\n", dp->filename, - dp->filename); - if (dp->attribute & FA_DIREC) { - if (attrib & DDL_DIRECTORY && strcmp(dp->filename, ".") != 0) { - sprintf(temp, "[%s]", dp->filename); - if (ListBoxAddString(lphl, temp) == LB_ERR) break; - } - } - else { - if (attrib & DDL_EXCLUSIVE) { - if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM)) { - if (ListBoxAddString(lphl, dp->filename) == LB_ERR) break; - } - } else { - if (ListBoxAddString(lphl, dp->filename) == LB_ERR) break; - } + + if (!(maskPtr = DOSFS_ToDosFCBFormat( filespec ))) return 0; + strcpy( mask, maskPtr ); + if (!(pathPtr = DOSFS_GetUnixFileName( ".", TRUE ))) return 0; + lstrcpyn( path, pathPtr, sizeof(path) ); + skip = 0; + drive = DRIVE_GetCurrentDrive(); + + while ((count = DOSFS_FindNext( path, mask, drive, + attrib, skip, &entry )) > 0) + { + skip += count; + if (entry.attr & FA_DIRECTORY) + { + if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ".")) + { + sprintf(temp, "[%s]", entry.name); + if (ListBoxAddString(lphl, temp) == LB_ERR) break; + } + } + else /* not a directory */ + { + if (!(attrib & DDL_EXCLUSIVE) || + ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) == + (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)))) + { + if (ListBoxAddString(lphl, entry.name) == LB_ERR) break; + } + } } - } - DOS_closedir(dp_old); - - if (attrib & DDL_DRIVES) { - int x; - for (x = 0; x != MAX_DOS_DRIVES ; x++) { - if (DOS_ValidDrive(x)) { - sprintf(temp, "[-%c-]", 'a'+x); - if (ListBoxInsertString(lphl, (UINT)-1, temp) == LB_ERR) break; - } + + if (attrib & DDL_DRIVES) + { + int x; + for (x = 0; x < MAX_DOS_DRIVES; x++) + { + if (DRIVE_IsValid(x)) + { + sprintf(temp, "[-%c-]", 'a'+x); + if (ListBoxInsertString(lphl, (UINT)-1, temp) == LB_ERR) break; + } + } } - } - return 1; + return 1; } /* ------------------------- dimensions ------------------------- */ @@ -1923,45 +1939,26 @@ BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox) /************************************************************************ * DlgDirList [USER.100] */ -int DlgDirList(HWND hDlg, LPSTR lpPathSpec, - int nIDLBox, int nIDStat, WORD wType) +INT DlgDirList( HWND hDlg, SEGPTR path, INT idLBox, INT idStatic, WORD wType ) { - HWND hWnd; - int ret; + INT ret = 0; - dprintf_listbox(stddeb,"DlgDirList("NPFMT", '%s', %d, %d, %04X) \n", - hDlg, lpPathSpec, nIDLBox, nIDStat, wType); - if (nIDLBox) { - LPHEADLIST lphl; - hWnd = GetDlgItem(hDlg, nIDLBox); - lphl = ListBoxGetStorageHeader(hWnd); - ListBoxResetContent(lphl); - ret = ListBoxDirectory(lphl, wType, lpPathSpec); - ListBoxUpdateWindow(hWnd, lphl, TRUE); - } else { - ret = 0; - } - if (nIDStat) { - int drive; - HANDLE hTemp; - char *temp; - drive = DOS_GetDefaultDrive(); - hTemp = USER_HEAP_ALLOC( 256 ); - temp = (char *) USER_HEAP_LIN_ADDR( hTemp ); - strcpy( temp+3, DOS_GetCurrentDir(drive) ); - if( temp[3] == '\\' ) { - temp[1] = 'A'+drive; - temp[2] = ':'; - SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0, - (LPARAM)(USER_HEAP_SEG_ADDR(hTemp) + 1) ); - } else { - temp[0] = 'A'+drive; - temp[1] = ':'; - temp[2] = '\\'; - SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0, - (LPARAM)USER_HEAP_SEG_ADDR(hTemp) ); - } - USER_HEAP_FREE( hTemp ); - } - return ret; + dprintf_listbox( stddeb, "DlgDirList("NPFMT", %08lx, %d, %d, %04X) \n", + hDlg, (DWORD)path, idLBox, idStatic, wType ); + if (idLBox) + { + SendDlgItemMessage( hDlg, idLBox, LB_RESETCONTENT, 0, 0 ); + ret = (SendDlgItemMessage( hDlg, idLBox, LB_DIR, wType, path ) >= 0); + } + if (idStatic) + { + char temp[256]; + int drive = DRIVE_GetCurrentDrive(); + strcpy( temp, "A:\\" ); + temp[0] += drive; + lstrcpyn( temp+3, DRIVE_GetDosCwd(drive), 253 ); + SendDlgItemMessage( hDlg, idStatic, WM_SETTEXT, + 0, (LPARAM)MAKE_SEGPTR(temp) ); + } + return ret; } diff --git a/controls/menu.c b/controls/menu.c index 63f424d4d03..e820d181913 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -57,7 +57,6 @@ extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down); /* nonclient.c */ static HBITMAP hStdCheck = 0; static HBITMAP hStdMnArrow = 0; -HMENU CopySysMenu(); WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu); @@ -102,6 +101,30 @@ static BOOL MENU_HasSysMenu( POPUPMENU *menu ) } +/********************************************************************** + * MENU_CopySysMenu + */ +static HMENU MENU_CopySysMenu(void) +{ + HMENU hMenu; + HGLOBAL handle; + POPUPMENU *menu; + + if (!(handle = SYSRES_LoadResource( SYSRES_MENU_SYSMENU ))) return 0; + hMenu = LoadMenuIndirect( GlobalLock( handle ) ); + SYSRES_FreeResource( handle ); + if (!hMenu) + { + dprintf_menu(stddeb,"No SYSMENU\n"); + return 0; + } + menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu); + menu->wFlags |= MF_SYSMENU | MF_POPUP; + dprintf_menu(stddeb,"CopySysMenu hMenu="NPFMT" !\n", hMenu); + return hMenu; +} + + /*********************************************************************** * MENU_IsInSysMenu * @@ -1549,8 +1572,10 @@ BOOL ChangeMenu(HMENU hMenu, UINT nPos, LPSTR lpNewItem, return AppendMenu(hMenu, wFlags & ~MF_APPEND, wItemID, lpNewItem); } if (wFlags & MF_DELETE) { - return DeleteMenu(hMenu, wFlags & MF_BYPOSITION ? nPos : wItemID, - wFlags & ~MF_DELETE); + /* FIXME: Word passes the item id in nPos and 0 or 0xffff as id */ + /* for MF_DELETE. We should check the parameters for all others */ + /* MF_* actions also (anybody got a doc on ChangeMenu?). */ + return DeleteMenu(hMenu, nPos, wFlags & ~MF_DELETE); } if (wFlags & MF_CHANGE) { return ModifyMenu(hMenu, nPos, wFlags & ~MF_CHANGE, wItemID, lpNewItem); @@ -2015,8 +2040,8 @@ HMENU GetSystemMenu(HWND hWnd, BOOL bRevert) if (!wndPtr) return 0; if (!bRevert) return wndPtr->hSysMenu; - DestroyMenu(wndPtr->hSysMenu); - wndPtr->hSysMenu = CopySysMenu(); + if (wndPtr->hSysMenu) DestroyMenu(wndPtr->hSysMenu); + wndPtr->hSysMenu = MENU_CopySysMenu(); return wndPtr->hSysMenu; } @@ -2180,30 +2205,6 @@ HMENU LoadMenuIndirect(LPSTR menu_template) } -/********************************************************************** - * CopySysMenu (Internal) - */ -HMENU CopySysMenu() -{ - HMENU hMenu; - HGLOBAL handle; - LPPOPUPMENU menu; - - if (!(handle = SYSRES_LoadResource( SYSRES_MENU_SYSMENU ))) return 0; - hMenu = LoadMenuIndirect( GlobalLock( handle ) ); - SYSRES_FreeResource( handle ); - if(!hMenu) - { - dprintf_menu(stddeb,"No SYSMENU\n"); - return 0; - } - menu = (POPUPMENU*) USER_HEAP_LIN_ADDR(hMenu); - menu->wFlags |= MF_SYSMENU|MF_POPUP; - dprintf_menu(stddeb,"CopySysMenu hMenu="NPFMT" !\n", hMenu); - return hMenu; -} - - /********************************************************************** * ParseMenuResource (from Resource or Template) */ diff --git a/controls/scroll.c b/controls/scroll.c index 3d7a67e8db2..ff63e0830ae 100644 --- a/controls/scroll.c +++ b/controls/scroll.c @@ -770,7 +770,7 @@ LONG ScrollBarWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam ) if (lpCreat->style & SBS_SIZEBOX) { fprintf( stdnimp, "Unimplemented style SBS_SIZEBOX.\n" ); - return -1; + return 0; /* FIXME */ } if (lpCreat->style & SBS_VERT) diff --git a/debugger/debug.l b/debugger/debug.l index e6de8fcc1b3..50c66d73d48 100644 --- a/debugger/debug.l +++ b/debugger/debug.l @@ -10,6 +10,7 @@ #include #include #include "debugger.h" +#include "xmalloc.h" #include "y.tab.h" #ifdef USE_READLINE @@ -202,7 +203,7 @@ static char *local_symbols[10]; static int next_symbol; char * make_symbol(char * symbol){ - return local_symbols[next_symbol++] = strdup(symbol); + return local_symbols[next_symbol++] = xstrdup(symbol); } void diff --git a/debugger/hash.c b/debugger/hash.c index 8a325c7a09c..60be9104e6b 100644 --- a/debugger/hash.c +++ b/debugger/hash.c @@ -51,7 +51,7 @@ void DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr ) new = (struct name_hash *) xmalloc(sizeof(struct name_hash)); new->addr = *addr; - new->name = strdup(name); + new->name = xstrdup(name); new->next = NULL; hash = name_hash(name); diff --git a/debugger/stack.c b/debugger/stack.c index 9b4e09fe8a4..de541605b7b 100644 --- a/debugger/stack.c +++ b/debugger/stack.c @@ -66,6 +66,10 @@ void DEBUG_BackTrace(void) if (SS_reg(DEBUG_context) == WINE_DATA_SELECTOR) /* 32-bit mode */ { addr.seg = 0; + fprintf(stderr,"%d ",frameno++); + addr.off = EIP_reg(DEBUG_context); + DEBUG_PrintAddress( &addr, 32 ); + fprintf( stderr, "\n" ); addr.off = EBP_reg(DEBUG_context); for (;;) { @@ -87,7 +91,12 @@ void DEBUG_BackTrace(void) fprintf( stderr, "Not implemented: 32-bit backtrace on a different stack segment.\n" ); return; } - addr.seg = SS_reg(DEBUG_context); + fprintf( stderr,"%d ", frameno++ ); + addr.seg = cs; + addr.off = IP_reg(DEBUG_context); + DEBUG_PrintAddress( &addr, 16 ); + fprintf( stderr, "\n" ); + addr.seg = ss; addr.off = BP_reg(DEBUG_context) & ~1; for (;;) { diff --git a/documentation/languages b/documentation/languages new file mode 100644 index 00000000000..e51262e3905 --- /dev/null +++ b/documentation/languages @@ -0,0 +1,64 @@ +This file documents the necessary procedure for adding a new language +to the list of languages that Wine can display system menus and forms +in. + +To add a new language you need to be able to translate the relatively +few texts, of course. You will need very little knowledge of +programming, so you have almost no excuses for not adding your language, +right? We should easily be able to support 20 languages within a few +months, get going! Apart from re-compilation it'll take you about an +hour. + +To add a new language to the list of languages that Wine can handle +you must... + +1. Edit resources/Makefile.in variable "LANGUAGES" to include a new + abbreviation for the language. + +2. Edit ./wine.man (search for -language) to show the new language + abbreviation. + +3. Edit misc/main.c variable "langNames" to contain the new language + abbreviation. Also edit macro "USAGE" to show the new abbreviation. + +4. Edit include/options.h enum "WINE_LANGUAGE" to have a member called + LANG_XX where XX is the new abbreviation. + +5. Edit misc/ole2nls.c function "GetUserDefaultLCID" to contain an + extra case for your language. The correct return values seem to + be a mystery, but don't worry. + +6. Edit resources/sysrec.c to include "sysres_XX.h" where XX is the + abbreviation for your language. (That file will be produced auto- + matically.) Edit variable "SYSRES_Resources" to contain an entry + for your language. + +7. Create a new file, resources/sysres_XX.rc, where XX is the + abbreviation that you chose. Your best bet is to copy one of the + other *.rc files and start translating. [Warning: the author of + this file does not know the details of the structure of these + files. There seems to be no need to, however.] + + In menus, the character "&" means that the next character will + be highlighted and that pressing that letter will select the item. + You should place these "&"s suitably for your language, not just + copy the positions from (say) English. In particular, items within + one menu should have different highlighted letters. + +8. Edit misc/ole2nls.c function "GetLocaleInfoA" to contain a case for + your language. + +9. Re-configure, re-make dependencies, and re-make Wine. + +10. Check your new menus and forms; when they're ok, submit patches + for inclusion in the next Wine release, see file ./ANNOUNCE for + details about where to submit. + + +January 1996 +Morten Welinder + +[I hope I got all the places where changes are needed. If you see any +place missing from the above list, submit a patch to this file please. +Also note that re-organization of the source code might change the list +of places.] diff --git a/files/Makefile.in b/files/Makefile.in new file mode 100644 index 00000000000..5fee0609b18 --- /dev/null +++ b/files/Makefile.in @@ -0,0 +1,14 @@ +TOPSRC = @top_srcdir@ +MODULE = files + +C_SRCS = \ + directory.c \ + dos_fs.c \ + drive.c \ + file.c + +all: $(MODULE).o + +@MAKE_RULES@ + +### Dependencies: diff --git a/files/directory.c b/files/directory.c new file mode 100644 index 00000000000..9de0c5289f6 --- /dev/null +++ b/files/directory.c @@ -0,0 +1,245 @@ +/* + * DOS directories functions + * + * Copyright 1995 Alexandre Julliard + */ + +#include +#include +#include + +#include "windows.h" +#include "dos_fs.h" +#include "drive.h" +#include "file.h" +#include "msdos.h" +#include "xmalloc.h" +#include "stddebug.h" +#include "debug.h" + +#define MAX_PATH_ELEMENTS 20 + +static char *DIR_WindowsDosDir; +static char *DIR_WindowsUnixDir; +static char *DIR_SystemDosDir; +static char *DIR_SystemUnixDir; +static char *DIR_TempDosDir; +static char *DIR_TempUnixDir; + +static char *DIR_DosPath[MAX_PATH_ELEMENTS]; /* Path in DOS format */ +static char *DIR_UnixPath[MAX_PATH_ELEMENTS]; /* Path in Unix format */ +static int DIR_PathElements = 0; + +/*********************************************************************** + * DIR_GetPath + * + * Get a path name from the wine.ini file and make sure it is valid. + */ +static int DIR_GetPath( const char *keyname, const char *defval, + char **dos_path, char **unix_path ) +{ + char path[MAX_PATHNAME_LEN]; + const char *dos_name ,*unix_name; + BYTE attr; + + GetPrivateProfileString( "wine", keyname, defval, + path, sizeof(path), WineIniFileName() ); + if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) || + !FILE_Stat( unix_name, &attr, NULL, NULL, NULL ) || + !(attr & FA_DIRECTORY)) + { + fprintf(stderr, "Invalid path '%s' for %s directory\n", path, keyname); + return 0; + } + if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE ))) + { + fprintf( stderr, "Could not get DOS name for %s directory '%s'\n", + keyname, unix_name ); + return 0; + } + *unix_path = xstrdup( unix_name ); + *dos_path = xstrdup( dos_name ); + return 1; +} + + +/*********************************************************************** + * DIR_ParseWindowsPath + */ +void DIR_ParseWindowsPath( char *path ) +{ + char *p; + const char *dos_name ,*unix_name; + BYTE attr; + int i; + + for ( ; path && *path; path = p) + { + p = strchr( path, ';' ); + if (p) while (*p == ';') *p++ = '\0'; + + if (DIR_PathElements >= MAX_PATH_ELEMENTS) + { + fprintf( stderr, "Warning: path has more than %d elements.\n", + MAX_PATH_ELEMENTS ); + break; + } + if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) || + !FILE_Stat( unix_name, &attr, NULL, NULL, NULL ) || + !(attr & FA_DIRECTORY)) + { + fprintf(stderr,"Warning: invalid dir '%s' in path, deleting it.\n", + path ); + continue; + } + if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE ))) + { + fprintf( stderr, "Warning: could not get DOS name for '%s' in path, deleting it.\n", + unix_name ); + continue; + } + DIR_UnixPath[DIR_PathElements] = xstrdup( unix_name ); + DIR_DosPath[DIR_PathElements] = xstrdup( dos_name ); + DIR_PathElements++; + } + + if (debugging_dosfs) + for (i = 0; i < DIR_PathElements; i++) + { + dprintf_dosfs( stddeb, "Path[%d]: %s = %s\n", + i, DIR_DosPath[i], DIR_UnixPath[i] ); + } +} + + +/*********************************************************************** + * DIR_Init + */ +int DIR_Init(void) +{ + char path[MAX_PATHNAME_LEN]; + int drive; + const char *cwd; + + if (!getcwd( path, MAX_PATHNAME_LEN )) + { + perror( "Could not get current directory" ); + return 0; + } + cwd = path; + if ((drive = DRIVE_FindDriveRoot( &cwd )) == -1) + { + fprintf( stderr, "Warning: could not find DOS drive for cwd %s; starting in windows directory.\n", + cwd ); + } + else + { + cwd = DOSFS_GetDosTrueName( path, TRUE ); + DRIVE_SetCurrentDrive( drive ); + DRIVE_Chdir( drive, cwd + 2 ); + } + + if (!(DIR_GetPath( "windows", "c:\\windows", + &DIR_WindowsDosDir, &DIR_WindowsUnixDir ))) return 0; + if (!(DIR_GetPath( "system", "c:\\windows\\system", + &DIR_SystemDosDir, &DIR_SystemUnixDir ))) return 0; + if (!(DIR_GetPath( "temp", "c:\\windows", + &DIR_TempDosDir, &DIR_TempUnixDir ))) return 0; + + if (drive == -1) + { + drive = DIR_WindowsDosDir[0] - 'A'; + DRIVE_SetCurrentDrive( drive ); + DRIVE_Chdir( drive, DIR_WindowsDosDir + 2 ); + } + + GetPrivateProfileString( "wine", "path", "c:\\windows;c:\\windows\\system", + path, sizeof(path), WineIniFileName() ); + DIR_ParseWindowsPath( path ); + + dprintf_dosfs( stddeb, "WindowsDir = %s\nSystemDir = %s\n", + DIR_WindowsDosDir, DIR_SystemDosDir ); + dprintf_dosfs( stddeb, "TempDir = %s\nCwd = %c:\\%s\n", + DIR_TempDosDir, 'A' + drive, DRIVE_GetDosCwd( drive ) ); + return 1; +} + + +/*********************************************************************** + * DIR_GetTempDosDir + */ +UINT DIR_GetTempDosDir( LPSTR path, UINT count ) +{ + if (path) lstrcpyn( path, DIR_TempDosDir, count ); + return strlen( DIR_TempDosDir ); +} + + +/*********************************************************************** + * DIR_GetTempUnixDir + */ +UINT DIR_GetTempUnixDir( LPSTR path, UINT count ) +{ + if (path) lstrcpyn( path, DIR_TempUnixDir, count ); + return strlen( DIR_TempUnixDir ); +} + + +/*********************************************************************** + * DIR_GetWindowsUnixDir + */ +UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count ) +{ + if (path) lstrcpyn( path, DIR_WindowsUnixDir, count ); + return strlen( DIR_WindowsUnixDir ); +} + + +/*********************************************************************** + * DIR_GetSystemUnixDir + */ +UINT DIR_GetSystemUnixDir( LPSTR path, UINT count ) +{ + if (path) lstrcpyn( path, DIR_SystemUnixDir, count ); + return strlen( DIR_SystemUnixDir ); +} + + +/*********************************************************************** + * DIR_GetDosPath + */ +UINT DIR_GetDosPath( int element, LPSTR path, UINT count ) +{ + if ((element < 0) || (element >= DIR_PathElements)) return 0; + if (path) lstrcpyn( path, DIR_DosPath[element], count ); + return strlen( DIR_DosPath[element] ); +} + + +/*********************************************************************** + * GetTempDrive (KERNEL.92) + */ +BYTE GetTempDrive( BYTE ignored ) +{ + return DIR_TempDosDir[0]; +} + + +/*********************************************************************** + * GetWindowsDirectory (KERNEL.134) + */ +UINT GetWindowsDirectory( LPSTR path, UINT count ) +{ + if (path) lstrcpyn( path, DIR_WindowsDosDir, count ); + return strlen( DIR_WindowsDosDir ); +} + + +/*********************************************************************** + * GetSystemDirectory (KERNEL.135) + */ +UINT GetSystemDirectory( LPSTR path, UINT count ) +{ + if (path) lstrcpyn( path, DIR_SystemDosDir, count ); + return strlen( DIR_SystemDosDir ); +} diff --git a/files/dos_fs.c b/files/dos_fs.c new file mode 100644 index 00000000000..6f4e921edbb --- /dev/null +++ b/files/dos_fs.c @@ -0,0 +1,689 @@ +/* + * DOS file system functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __svr4__ +#include +#endif + +#include "windows.h" +#include "dos_fs.h" +#include "drive.h" +#include "file.h" +#include "msdos.h" +#include "stddebug.h" +#include "debug.h" + +/* Chars we don't want to see in DOS file names */ +#define INVALID_DOS_CHARS "*?<>|\"+=,; " + +static const char *DOSFS_Devices[][2] = +{ + { "CON", "" }, + { "PRN", "" }, + { "NUL", "/dev/null" }, + { "AUX", "" }, + { "LPT1", "" }, + { "LPT2", "" }, + { "LPT3", "" }, + { "LPT4", "" }, + { "COM1", "" }, + { "COM2", "" }, + { "COM3", "" }, + { "COM4", "" } +}; + +#define GET_DRIVE(path) \ + (((path)[1] == ':') ? toupper((path)[0]) - 'A' : DOSFS_CurDrive) + + /* DOS extended error status */ +WORD DOS_ExtendedError; +BYTE DOS_ErrorClass; +BYTE DOS_ErrorAction; +BYTE DOS_ErrorLocus; + + +/*********************************************************************** + * DOSFS_ValidDOSName + * + * Return 1 if Unix file 'name' is also a valid MS-DOS name + * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format). + * File name can be terminated by '\0', '\\' or '/'. + */ +static int DOSFS_ValidDOSName( const char *name ) +{ + static const char invalid_chars[] = INVALID_DOS_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *p = name; + int len = 0; + + if (*p == '.') + { + /* Check for "." and ".." */ + p++; + if (*p == '.') p++; + /* All other names beginning with '.' are invalid */ + return (IS_END_OF_NAME(*p)); + } + while (!IS_END_OF_NAME(*p)) + { + if (strchr( invalid_chars, *p )) return 0; /* Invalid char */ + if (*p == '.') break; /* Start of the extension */ + if (++len > 8) return 0; /* Name too long */ + p++; + } + if (*p != '.') return 1; /* End of name */ + p++; + if (IS_END_OF_NAME(*p)) return 0; /* Empty extension not allowed */ + len = 0; + while (!IS_END_OF_NAME(*p)) + { + if (strchr( invalid_chars, *p )) return 0; /* Invalid char */ + if (*p == '.') return 0; /* Second extension not allowed */ + if (++len > 3) return 0; /* Extension too long */ + p++; + } + return 1; +} + + +/*********************************************************************** + * DOSFS_CheckDotDot + * + * Remove all '.' and '..' at the beginning of 'name'. + */ +static const char * DOSFS_CheckDotDot( const char *name, char *buffer, + char sep , int *len ) +{ + char *p = buffer + strlen(buffer); + + while (*name == '.') + { + if (IS_END_OF_NAME(name[1])) + { + name++; + while ((*name == '\\') || (*name == '/')) name++; + } + else if ((name[1] == '.') && IS_END_OF_NAME(name[2])) + { + name += 2; + while ((*name == '\\') || (*name == '/')) name++; + while ((p > buffer) && (*p != sep)) { p--; (*len)++; } + *p = '\0'; /* Remove trailing separator */ + } + else break; + } + return name; +} + + +/*********************************************************************** + * DOSFS_ToDosFCBFormat + * + * Convert a file name to DOS FCB format (8+3 chars, padded with blanks), + * expanding wild cards and converting to upper-case in the process. + * File name can be terminated by '\0', '\\' or '/'. + * Return NULL if the name is not a valid DOS name. + */ +const char *DOSFS_ToDosFCBFormat( const char *name ) +{ + static const char invalid_chars[] = INVALID_DOS_CHARS; + static char buffer[12]; + const char *p = name; + int i; + + /* Check for "." and ".." */ + if (*p == '.') + { + p++; + strcpy( buffer, ". " ); + if (*p == '.') p++; + return (!*p || (*p == '/') || (*p == '\\')) ? buffer : NULL; + } + + for (i = 0; i < 8; i++) + { + switch(*p) + { + case '\0': + case '\\': + case '/': + case '.': + buffer[i] = ' '; + break; + case '?': + p++; + /* fall through */ + case '*': + buffer[i] = '?'; + break; + default: + if (strchr( invalid_chars, *p )) return NULL; + buffer[i] = toupper(*p); + p++; + break; + } + } + + if (*p == '*') + { + /* Skip all chars after wildcard up to first dot */ + while (*p && (*p != '/') && (*p != '\\') && (*p != '.')) p++; + } + else + { + /* Check if name too long */ + if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return NULL; + } + if (*p == '.') p++; /* Skip dot */ + + for (i = 8; i < 11; i++) + { + switch(*p) + { + case '\0': + case '\\': + case '/': + buffer[i] = ' '; + break; + case '.': + return NULL; /* Second extension not allowed */ + case '?': + p++; + /* fall through */ + case '*': + buffer[i] = '?'; + break; + default: + if (strchr( invalid_chars, *p )) return NULL; + buffer[i] = toupper(*p); + p++; + break; + } + } + buffer[11] = '\0'; + return buffer; +} + + +/*********************************************************************** + * DOSFS_ToDosDTAFormat + * + * Convert a file name from FCB to DTA format (name.ext, null-terminated) + * converting to upper-case in the process. + * File name can be terminated by '\0', '\\' or '/'. + * Return NULL if the name is not a valid DOS name. + */ +const char *DOSFS_ToDosDTAFormat( const char *name ) +{ + static char buffer[13]; + char *p; + + memcpy( buffer, name, 8 ); + for (p = buffer + 8; (p > buffer) && (p[-1] == ' '); p--); + *p++ = '.'; + memcpy( p, name + 8, 3 ); + for (p += 3; p[-1] == ' '; p--); + if (p[-1] == '.') p--; + *p = '\0'; + return buffer; +} + + +/*********************************************************************** + * DOSFS_Match + * + * Check a DOS file name against a mask (both in FCB format). + */ +static int DOSFS_Match( const char *mask, const char *name ) +{ + int i; + for (i = 11; i > 0; i--, mask++, name++) + if ((*mask != '?') && (*mask != *name)) return 0; + return 1; +} + + +/*********************************************************************** + * DOSFS_ToDosDateTime + * + * Convert a Unix time in the DOS date/time format. + */ +void DOSFS_ToDosDateTime( time_t *unixtime, WORD *pDate, WORD *pTime ) +{ + struct tm *tm = localtime( unixtime ); + if (pTime) + *pTime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2); + if (pDate) + *pDate = ((tm->tm_year - 80) << 9) + (tm->tm_mon << 5) + tm->tm_mday; +} + + +/*********************************************************************** + * DOSFS_Hash + * + * Transform a Unix file name into a hashed DOS name. If the name is a valid + * DOS name, it is converted to upper-case; otherwise it is replaced by a + * hashed version that fits in 8.3 format. + * File name can be terminated by '\0', '\\' or '/'. + */ +static const char *DOSFS_Hash( const char *name, int dir_format ) +{ + static const char invalid_chars[] = INVALID_DOS_CHARS "~."; + static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"; + + static char buffer[13]; + const char *p, *ext; + char *dst; + unsigned short hash; + int i; + + if (dir_format) strcpy( buffer, " " ); + + if (DOSFS_ValidDOSName( name )) + { + /* Check for '.' and '..' */ + if (*name == '.') + { + buffer[0] = '.'; + if (!dir_format) buffer[1] = buffer[2] = '\0'; + if (name[1] == '.') buffer[1] = '.'; + return buffer; + } + + /* Simply copy the name, converting to uppercase */ + + for (dst = buffer; !IS_END_OF_NAME(*name) && (*name != '.'); name++) + *dst++ = toupper(*name); + if (*name == '.') + { + if (dir_format) dst = buffer + 8; + else *dst++ = '.'; + for (name++; !IS_END_OF_NAME(*name); name++) + *dst++ = toupper(*name); + } + if (!dir_format) *dst = '\0'; + } + else + { + /* Compute the hash code of the file name */ + /* If you know something about hash functions, feel free to */ + /* insert a better algorithm here... */ + for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++) + hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8); + hash = (hash << 3) ^ (hash >> 5) ^ *p; /* Last character */ + + /* Find last dot for start of the extension */ + for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++) + if (*p == '.') ext = p; + if (ext && IS_END_OF_NAME(ext[1])) + ext = NULL; /* Empty extension ignored */ + + /* Copy first 4 chars, replacing invalid chars with '_' */ + for (i = 4, p = name, dst = buffer; i > 0; i--, p++) + { + if (IS_END_OF_NAME(*p) || (p == ext)) break; + *dst++ = strchr( invalid_chars, *p ) ? '_' : toupper(*p); + } + /* Pad to 5 chars with '~' */ + while (i-- >= 0) *dst++ = '~'; + + /* Insert hash code converted to 3 ASCII chars */ + *dst++ = hash_chars[(hash >> 10) & 0x1f]; + *dst++ = hash_chars[(hash >> 5) & 0x1f]; + *dst++ = hash_chars[hash & 0x1f]; + + /* Copy the first 3 chars of the extension (if any) */ + if (ext) + { + if (!dir_format) *dst++ = '.'; + for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++) + *dst++ = toupper(*ext); + } + if (!dir_format) *dst = '\0'; + } + return buffer; +} + + +/*********************************************************************** + * DOSFS_FindUnixName + * + * Find the Unix file name in a given directory that corresponds to + * a file name (either in Unix or DOS format). + * File name can be terminated by '\0', '\\' or '/'. + * Return 1 if OK, 0 if no file name matches. + */ +static int DOSFS_FindUnixName( const char *path, const char *name, + char *buffer, int maxlen ) +{ + DIR *dir; + struct dirent *dirent; + + const char *dos_name = DOSFS_ToDosFCBFormat( name ); + const char *p = strchr( name, '/' ); + int len = p ? (int)(p - name) : strlen(name); + + dprintf_dosfs( stddeb, "DOSFS_FindUnixName: %s %s\n", path, name ); + + if ((p = strchr( name, '\\' ))) len = MIN( (int)(p - name), len ); + + if (!(dir = opendir( path ))) + { + dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s): can't open dir\n", + path, name ); + return 0; + } + while ((dirent = readdir( dir )) != NULL) + { + /* Check against Unix name */ + if ((len == strlen(dirent->d_name) && + !memcmp( dirent->d_name, name, len ))) break; + if (dos_name) + { + /* Check against hashed DOS name */ + const char *hash_name = DOSFS_Hash( dirent->d_name, TRUE ); + if (!strcmp( dos_name, hash_name )) break; + } + } + if (dirent) lstrcpyn( buffer, dirent->d_name, maxlen ); + closedir( dir ); + dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s) -> %s\n", + path, name, dirent ? buffer : "** Not found **" ); + return (dirent != NULL); +} + + +/*********************************************************************** + * DOSFS_IsDevice + * + * Check if a DOS file name represents a DOS device. Returns the name + * of the associated Unix device, or NULL if not found. + */ +const char *DOSFS_IsDevice( const char *name ) +{ + int i; + const char *p; + + if (name[1] == ':') name += 2; + if ((p = strrchr( name, '/' ))) name = p + 1; + if ((p = strrchr( name, '\\' ))) name = p + 1; + for (i = 0; i < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0]); i++) + { + const char *dev = DOSFS_Devices[i][0]; + if (!lstrncmpi( dev, name, strlen(dev) )) + { + p = name + strlen( dev ); + if (*p == ':') p++; + if (!*p || (*p == '.')) return DOSFS_Devices[i][1]; + } + } + return NULL; +} + + +/*********************************************************************** + * DOSFS_GetUnixFileName + * + * Convert a file name (DOS or mixed DOS/Unix format) to a valid Unix name. + * Return NULL if one of the path components does not exist. The last path + * component is only checked if 'check_last' is non-zero. + */ +const char * DOSFS_GetUnixFileName( const char * name, int check_last ) +{ + static char buffer[MAX_PATHNAME_LEN]; + int drive, len, found; + char *p, *root; + + dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: %s\n", name ); + if (name[1] == ':') + { + drive = toupper(name[0]) - 'A'; + name += 2; + } + else if (name[0] == '/') /* Absolute Unix path? */ + { + if ((drive = DRIVE_FindDriveRoot( &name )) == -1) + { + fprintf( stderr, "Warning: %s not accessible from a DOS drive\n", + name ); + /* Assume it really was a DOS name */ + drive = DRIVE_GetCurrentDrive(); + } + } + else drive = DRIVE_GetCurrentDrive(); + + if (!DRIVE_IsValid(drive)) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + return NULL; + } + lstrcpyn( buffer, DRIVE_GetRoot(drive), MAX_PATHNAME_LEN ); + if (buffer[1]) root = buffer + strlen(buffer); + else root = buffer; /* root directory */ + + if ((*name == '\\') || (*name == '/')) + { + while ((*name == '\\') || (*name == '/')) name++; + } + else + { + lstrcpyn( root + 1, DRIVE_GetUnixCwd(drive), + MAX_PATHNAME_LEN - (int)(root - buffer) - 1 ); + if (root[1]) *root = '/'; + } + + p = buffer[1] ? buffer + strlen(buffer) : buffer; + len = MAX_PATHNAME_LEN - strlen(buffer); + found = 1; + while (*name && found) + { + const char *newname = DOSFS_CheckDotDot( name, root, '/', &len ); + if (newname != name) + { + p = root + strlen(root); + name = newname; + continue; + } + if (len <= 1) + { + DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return NULL; + } + if ((found = DOSFS_FindUnixName( buffer, name, p+1, len-1 ))) + { + *p = '/'; + len -= strlen(p); + p += strlen(p); + while (!IS_END_OF_NAME(*name)) name++; + } + else + { + *p++ = '/'; + for (len--; !IS_END_OF_NAME(*name) && (len > 1); name++, len--) + *p++ = tolower(*name); + *p = '\0'; + } + while ((*name == '\\') || (*name == '/')) name++; + } + if (!found) + { + if (*name) /* Not last */ + { + DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return NULL; + } + if (check_last) + { + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return NULL; + } + } + if (!buffer[0]) strcpy( buffer, "/" ); + dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: returning %s\n", buffer ); + return buffer; +} + + +/*********************************************************************** + * DOSFS_GetDosTrueName + * + * Convert a file name (DOS or Unix format) to a complete DOS name. + * Return NULL if the path name is invalid or too long. + * The unix_format flag is a hint that the file name is in Unix format. + */ +const char * DOSFS_GetDosTrueName( const char *name, int unix_format ) +{ + static char buffer[MAX_PATHNAME_LEN]; + int drive, len; + char *p; + + dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName(%s,%d)\n", name, unix_format); + if (name[1] == ':') + { + drive = toupper(name[0]) - 'A'; + name += 2; + } + else if (name[0] == '/') /* Absolute Unix path? */ + { + if ((drive = DRIVE_FindDriveRoot( &name )) == -1) + { + fprintf( stderr, "Warning: %s not accessible from a DOS drive\n", + name ); + /* Assume it really was a DOS name */ + drive = DRIVE_GetCurrentDrive(); + } + } + else drive = DRIVE_GetCurrentDrive(); + + if (!DRIVE_IsValid(drive)) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + return NULL; + } + + strcpy( buffer, "A:\\" ); + buffer[0] += drive; + if ((name[0] == '\\') || (name[0] == '/')) + { + while ((*name == '\\') || (*name == '/')) name++; + p = buffer + 2; + } + else + { + lstrcpyn( buffer + 3, DRIVE_GetDosCwd(drive), len - 3 ); + if (buffer[3]) p = buffer + strlen(buffer); + else p = buffer + 2; + } + len = MAX_PATHNAME_LEN - (int)(p - buffer); + + while (*name) + { + const char *newname = DOSFS_CheckDotDot( name, buffer+2, '\\', &len ); + if (newname != name) + { + p = buffer + strlen(buffer); + name = newname; + continue; + } + if (len <= 1) + { + DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return NULL; + } + *p++ = '\\'; + if (unix_format) /* Hash it into a DOS name */ + { + lstrcpyn( p, DOSFS_Hash( name, FALSE ), len ); + len -= strlen(p); + p += strlen(p); + while (!IS_END_OF_NAME(*name)) name++; + } + else /* Already DOS format, simply upper-case it */ + { + while (!IS_END_OF_NAME(*name) && (len > 1)) + { + *p++ = toupper(*name); + name++; + len--; + } + } + while ((*name == '\\') || (*name == '/')) name++; + } + *p = '\0'; + if (!buffer[2]) + { + buffer[2] = '\\'; + buffer[3] = '\0'; + } + dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName: returning %s\n", buffer ); + return buffer; +} + + +/*********************************************************************** + * DOSFS_FindNext + * + * Find the next matching file. Return the number of entries read to find + * the matching one, or 0 if no more entries. + */ +int DOSFS_FindNext( const char *path, const char *mask, int drive, + BYTE attr, int skip, DOS_DIRENT *entry ) +{ + DIR *dir; + struct dirent *dirent; + int count = 0; + char buffer[MAX_PATHNAME_LEN], *p; + const char *hash_name; + + if ((attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL) + { + time_t now = time(NULL); + if (skip) return 0; + strcpy( entry->name, DRIVE_GetLabel( drive ) ); + entry->attr = FA_LABEL; + entry->size = 0; + DOSFS_ToDosDateTime( &now, &entry->date, &entry->time ); + return 1; + } + + if (!(dir = opendir( path ))) return 0; + strcpy( buffer, path ); + strcat( buffer, "/" ); + p = buffer + strlen(buffer); + attr |= FA_UNUSED | FA_ARCHIVE | FA_RDONLY; + + while ((dirent = readdir( dir )) != NULL) + { + if (skip-- > 0) continue; + count++; + hash_name = DOSFS_Hash( dirent->d_name, TRUE ); + if (!DOSFS_Match( mask, hash_name )) continue; + strcpy( p, dirent->d_name ); + + if (!FILE_Stat( buffer, &entry->attr, &entry->size, + &entry->date, &entry->time )) + { + fprintf( stderr, "DOSFS_FindNext: can't stat %s\n", buffer ); + continue; + } + if (entry->attr & ~attr) continue; + strcpy( entry->name, hash_name ); + lstrcpyn( entry->unixname, dirent->d_name, sizeof(entry->unixname) ); + dprintf_dosfs( stddeb, "DOSFS_FindNext: returning %s %02x %ld\n", + entry->name, entry->attr, entry->size ); + closedir( dir ); + return count; + } + closedir( dir ); + return 0; /* End of directory */ +} diff --git a/files/drive.c b/files/drive.c new file mode 100644 index 00000000000..ae2558d6af7 --- /dev/null +++ b/files/drive.c @@ -0,0 +1,349 @@ +/* + * DOS drive handling functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#include + +#include "windows.h" +#include "dos_fs.h" +#include "drive.h" +#include "file.h" +#include "msdos.h" +#include "task.h" +#include "xmalloc.h" +#include "stddebug.h" +#include "debug.h" + +typedef struct +{ + char *root; /* root dir in Unix format without trailing '/' */ + char *dos_cwd; /* cwd in DOS format without leading or trailing '\' */ + char *unix_cwd; /* cwd in Unix format without leading or trailing '/' */ + char label[12]; /* drive label */ + DWORD serial; /* drive serial number */ + WORD type; /* drive type */ + BYTE disabled; /* disabled flag */ +} DOSDRIVE; + +static DOSDRIVE DOSDrives[MAX_DOS_DRIVES]; +static int DRIVE_CurDrive = 0; + +static HTASK DRIVE_LastTask = 0; + +/*********************************************************************** + * DRIVE_Init + */ +int DRIVE_Init(void) +{ + int i, count = 0; + char drive[2] = "A"; + char path[MAX_PATHNAME_LEN]; + char *p; + + for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++) + { + GetPrivateProfileString( "drives", drive, "", + path, sizeof(path)-1, WineIniFileName() ); + if (path[0]) + { + p = path + strlen(path) - 1; + while ((p > path) && ((*p == '/') || (*p == '\\'))) *p-- = '\0'; + DOSDrives[i].root = xstrdup( path ); + DOSDrives[i].dos_cwd = xstrdup( "" ); + DOSDrives[i].unix_cwd = xstrdup( "" ); + sprintf( DOSDrives[i].label, "DRIVE-%c ", drive[0] ); + DOSDrives[i].serial = 0x12345678; + DOSDrives[i].type = (i < 2) ? DRIVE_REMOVABLE : DRIVE_FIXED; + DOSDrives[i].disabled = 0; + count++; + } + dprintf_dosfs( stddeb, "Drive %c -> %s\n", 'A' + i, + path[0] ? path : "** None **" ); + } + + if (!count) + { + fprintf( stderr, "Warning: no valid DOS drive found\n" ); + /* Create a C drive pointing to Unix root dir */ + DOSDrives[i].root = xstrdup( "/" ); + DOSDrives[i].dos_cwd = xstrdup( "" ); + DOSDrives[i].unix_cwd = xstrdup( "" ); + sprintf( DOSDrives[i].label, "DRIVE-%c ", drive[0] ); + DOSDrives[i].serial = 0x12345678; + DOSDrives[i].type = DRIVE_FIXED; + DOSDrives[i].disabled = 0; + } + + /* Make the first hard disk the current drive */ + for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++) + { + if (DOSDrives[i].root && !DOSDrives[i].disabled && + DOSDrives[i].type != DRIVE_REMOVABLE) + { + DRIVE_CurDrive = i; + break; + } + } + return 1; +} + + +/*********************************************************************** + * DRIVE_IsValid + */ +int DRIVE_IsValid( int drive ) +{ + if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0; + return (DOSDrives[drive].root && !DOSDrives[drive].disabled); +} + + +/*********************************************************************** + * DRIVE_GetCurrentDrive + */ +int DRIVE_GetCurrentDrive(void) +{ + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + if (pTask && (pTask->curdrive & 0x80)) return pTask->curdrive & ~0x80; + return DRIVE_CurDrive; +} + + +/*********************************************************************** + * DRIVE_SetCurrentDrive + */ +int DRIVE_SetCurrentDrive( int drive ) +{ + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + if (!DRIVE_IsValid( drive )) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + return 0; + } + dprintf_dosfs( stddeb, "DRIVE_SetCurrentDrive: %c:\n", 'A' + drive ); + DRIVE_CurDrive = drive; + if (pTask) pTask->curdrive = drive | 0x80; + return 1; +} + + +/*********************************************************************** + * DRIVE_FindDriveRoot + * + * Find a drive for which the root matches the begginning of the given path. + * This can be used to translate a Unix path into a drive + DOS path. + * Return value is the drive, or -1 on error. On success, path is modified + * to point to the beginning of the DOS path. + * FIXME: this only does a textual comparison of the path names, and won't + * work well in the presence of symbolic links. + */ +int DRIVE_FindDriveRoot( const char **path ) +{ + int drive; + const char *p1, *p2; + + dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: searching '%s'\n", *path ); + for (drive = 0; drive < MAX_DOS_DRIVES; drive++) + { + if (!DOSDrives[drive].root || DOSDrives[drive].disabled) continue; + p1 = *path; + p2 = DOSDrives[drive].root; + dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: checking %c: '%s'\n", + 'A' + drive, p2 ); + for (;;) + { + while ((*p1 == '\\') || (*p1 == '/')) p1++; + while (*p2 == '/') p2++; + while ((*p1 == *p2) && (*p2) && (*p2 != '/')) p1++, p2++; + if (!*p2) + { + if (IS_END_OF_NAME(*p1)) /* OK, found it */ + { + *path = p1; + return drive; + } + } + else if (*p2 == '/') + { + if (IS_END_OF_NAME(*p1)) + continue; /* Go to next path element */ + } + break; /* No match, go to next drive */ + } + } + return -1; +} + + +/*********************************************************************** + * DRIVE_GetRoot + */ +const char * DRIVE_GetRoot( int drive ) +{ + if (!DRIVE_IsValid( drive )) return NULL; + return DOSDrives[drive].root; +} + + +/*********************************************************************** + * DRIVE_GetDosCwd + */ +const char * DRIVE_GetDosCwd( int drive ) +{ + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + if (!DRIVE_IsValid( drive )) return NULL; + + /* Check if we need to change the directory to the new task. */ + if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */ + ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */ + (DRIVE_LastTask != GetCurrentTask())) /* and the task changed */ + { + /* Perform the task-switch */ + if (!DRIVE_Chdir( drive, pTask->curdir )) DRIVE_Chdir( drive, "\\" ); + DRIVE_LastTask = GetCurrentTask(); + } + return DOSDrives[drive].dos_cwd; +} + + +/*********************************************************************** + * DRIVE_GetUnixCwd + */ +const char * DRIVE_GetUnixCwd( int drive ) +{ + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + if (!DRIVE_IsValid( drive )) return NULL; + + /* Check if we need to change the directory to the new task. */ + if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */ + ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */ + (DRIVE_LastTask != GetCurrentTask())) /* and the task changed */ + { + /* Perform the task-switch */ + if (!DRIVE_Chdir( drive, pTask->curdir )) DRIVE_Chdir( drive, "\\" ); + DRIVE_LastTask = GetCurrentTask(); + } + return DOSDrives[drive].unix_cwd; +} + + +/*********************************************************************** + * DRIVE_GetLabel + */ +const char * DRIVE_GetLabel( int drive ) +{ + if (!DRIVE_IsValid( drive )) return NULL; + return DOSDrives[drive].label; +} + + +/*********************************************************************** + * DRIVE_GetSerialNumber + */ +DWORD DRIVE_GetSerialNumber( int drive ) +{ + if (!DRIVE_IsValid( drive )) return 0; + return DOSDrives[drive].serial; +} + + +/*********************************************************************** + * DRIVE_SetSerialNumber + */ +int DRIVE_SetSerialNumber( int drive, DWORD serial ) +{ + if (!DRIVE_IsValid( drive )) return 0; + DOSDrives[drive].serial = serial; + return 1; +} + + +/*********************************************************************** + * DRIVE_Chdir + */ +int DRIVE_Chdir( int drive, const char *path ) +{ + char buffer[MAX_PATHNAME_LEN]; + const char *unix_cwd, *dos_cwd; + BYTE attr; + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + + dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:,%s)\n", 'A' + drive, path ); + strcpy( buffer, "A:" ); + buffer[0] += drive; + lstrcpyn( buffer + 2, path, sizeof(buffer) - 2 ); + + if (!(unix_cwd = DOSFS_GetUnixFileName( buffer, TRUE ))) return 0; + if (!FILE_Stat( unix_cwd, &attr, NULL, NULL, NULL )) return 0; + if (!(attr & FA_DIRECTORY)) + { + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return 0; + } + unix_cwd += strlen( DOSDrives[drive].root ); + while (*unix_cwd == '/') unix_cwd++; + buffer[2] = '/'; + lstrcpyn( buffer + 3, unix_cwd, sizeof(buffer) - 3 ); + if (!(dos_cwd = DOSFS_GetDosTrueName( buffer, TRUE ))) return 0; + + dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:): unix_cwd=%s dos_cwd=%s\n", + 'A' + drive, unix_cwd, dos_cwd + 3 ); + + free( DOSDrives[drive].dos_cwd ); + free( DOSDrives[drive].unix_cwd ); + DOSDrives[drive].dos_cwd = xstrdup( dos_cwd + 3 ); + DOSDrives[drive].unix_cwd = xstrdup( unix_cwd ); + + if (pTask && (pTask->curdrive & 0x80) && + ((pTask->curdrive & ~0x80) == drive)) + { + lstrcpyn( pTask->curdir, dos_cwd + 2, sizeof(pTask->curdir) ); + DRIVE_LastTask = GetCurrentTask(); + } + return 1; +} + + +/*********************************************************************** + * DRIVE_Disable + */ +int DRIVE_Disable( int drive ) +{ + if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + return 0; + } + DOSDrives[drive].disabled = 1; + return 1; +} + + +/*********************************************************************** + * DRIVE_Enable + */ +int DRIVE_Enable( int drive ) +{ + if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + return 0; + } + DOSDrives[drive].disabled = 0; + return 1; +} + + +/*********************************************************************** + * GetDriveType (KERNEL.136) + */ +WORD GetDriveType( INT drive ) +{ + dprintf_dosfs( stddeb, "GetDriveType(%c:)\n", 'A' + drive ); + if (!DRIVE_IsValid(drive)) return 0; + return DOSDrives[drive].type; +} diff --git a/files/file.c b/files/file.c new file mode 100644 index 00000000000..19cc6fb7f57 --- /dev/null +++ b/files/file.c @@ -0,0 +1,906 @@ +/* + * File handling functions + * + * Copyright 1993 John Burton + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windows.h" +#include "directory.h" +#include "dos_fs.h" +#include "drive.h" +#include "global.h" +#include "msdos.h" +#include "options.h" +#include "ldt.h" +#include "task.h" +#include "stddebug.h" +#include "debug.h" + + +/*********************************************************************** + * FILE_SetDosError + * + * Set the DOS error code from errno. + */ +void FILE_SetDosError(void) +{ + switch (errno) + { + case EAGAIN: + DOS_ERROR( ER_ShareViolation, EC_Temporary, SA_Retry, EL_Disk ); + break; + case EBADF: + DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk ); + break; + case ENOSPC: + DOS_ERROR( ER_DiskFull, EC_MediaError, SA_Abort, EL_Disk ); + break; + case EACCES: + case EPERM: + case EROFS: + DOS_ERROR( ER_WriteProtected, EC_AccessDenied, SA_Abort, EL_Disk ); + break; + case EBUSY: + DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Abort, EL_Disk ); + break; + case ENOENT: + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + break; + case EISDIR: + DOS_ERROR( ER_CanNotMakeDir, EC_AccessDenied, SA_Abort, EL_Unknown ); + break; + case ENFILE: + case EMFILE: + DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Unknown ); + break; + case EEXIST: + DOS_ERROR( ER_FileExists, EC_Exists, SA_Abort, EL_Disk ); + break; + default: + perror( "int21: unknown errno" ); + DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort, EL_Unknown ); + break; + } +} + + +/*********************************************************************** + * FILE_AllocTaskHandle + * + * Allocate a DOS file handle for the current task. + */ +static HFILE FILE_AllocTaskHandle( int handle ) +{ + PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); + BYTE *files, *fp; + WORD i; + + if (!pdb) + { + fprintf(stderr,"FILE_MakeTaskHandle: internal error, no current PDB.\n"); + exit(1); + } + fp = files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + for (i = pdb->nbFiles; (i > 0) && (*fp != 0xff); i--, fp++); + if (!i || (handle >= 0xff)) /* No more handles */ + { + DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk ); + return -1; + } + *fp = (BYTE)handle; + return (HFILE)(fp - files); +} + + +/*********************************************************************** + * FILE_FreeTaskHandle + * + * Free a DOS file handle for the current task. + */ +static void FILE_FreeTaskHandle( HFILE handle ) +{ + PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); + BYTE *files; + + if (!pdb) + { + fprintf(stderr,"FILE_FreeTaskHandle: internal error, no current PDB.\n"); + exit(1); + } + files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + if ((handle<0) || (handle >= (INT)pdb->nbFiles) || (files[handle] == 0xff)) + { + fprintf( stderr, "FILE_FreeTaskHandle: invalid file handle %d\n", + handle ); + return; + } + files[handle] = 0xff; +} + + +/*********************************************************************** + * FILE_GetUnixHandle + * + * Return the Unix file handle associated to a DOS file handle. + */ +int FILE_GetUnixHandle( HFILE handle ) +{ + PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); + BYTE *files; + + if (!pdb) + { + fprintf(stderr,"FILE_GetUnixHandle: internal error, no current PDB.\n"); + exit(1); + } + files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + if ((handle<0) || (handle >= (INT)pdb->nbFiles) || (files[handle] == 0xff)) + { + DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk ); + return -1; + } + return (int)files[handle]; +} + + +/*********************************************************************** + * FILE_CloseAllFiles + * + * Close all open files of a given PDB. Used on task termination. + */ +void FILE_CloseAllFiles( HANDLE hPDB ) +{ + BYTE *files; + WORD count; + PDB *pdb = (PDB *)GlobalLock( hPDB ); + + if (!pdb) return; + files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + for (count = pdb->nbFiles; count > 0; count--, files++) + { + if (*files != 0xff) + { + close( (int)*files ); + *files = 0xff; + } + } +} + + +/*********************************************************************** + * FILE_Open + */ +int FILE_Open( LPCSTR path, int mode ) +{ + const char *unixName; + int handle; + + dprintf_file(stddeb, "FILE_Open: '%s' %04x\n", path, mode ); + if ((unixName = DOSFS_IsDevice( path )) != NULL) + { + dprintf_file( stddeb, "FILE_Open: opening device '%s'\n", unixName ); + if (!unixName[0]) /* Non-existing device */ + { + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return -1; + } + handle = open( unixName, mode ); + } + else + { + if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return -1; + + if ((handle = open( unixName, mode )) == -1) + { + if (Options.allowReadOnly && (mode == O_RDWR)) + { + if ((handle = open( unixName, O_RDONLY )) != -1) + fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", unixName ); + } + } + } + if (handle == -1) FILE_SetDosError(); + return handle; +} + + +/*********************************************************************** + * FILE_Create + */ +int FILE_Create( LPCSTR path, int mode, int unique ) +{ + const char *unixName; + int handle; + + dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique ); + + if ((unixName = DOSFS_IsDevice( path )) != NULL) + { + dprintf_file(stddeb, "FILE_Create: creating device '%s'!\n", unixName); + DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk ); + return -1; + } + + if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return -1; + if ((handle = open( unixName, + O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0), + mode )) == -1) + FILE_SetDosError(); + return handle; +} + + +/*********************************************************************** + * FILE_Unlink + */ +int FILE_Unlink( LPCSTR path ) +{ + const char *unixName; + + dprintf_file(stddeb, "FILE_Unlink: '%s'\n", path ); + + if ((unixName = DOSFS_IsDevice( path )) != NULL) + { + dprintf_file(stddeb, "FILE_Unlink: removing device '%s'!\n", unixName); + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return 0; + } + + if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0; + if (unlink( unixName ) == -1) + { + FILE_SetDosError(); + return 0; + } + return 1; +} + + +/*********************************************************************** + * FILE_Stat + * + * Stat a Unix path name. Return 1 if OK. + */ +int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize, + WORD *pdate, WORD *ptime ) +{ + struct stat st; + + if (stat( unixName, &st ) == -1) + { + FILE_SetDosError(); + return 0; + } + if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0); + if (psize) *psize = st.st_size; + DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime ); + return 1; +} + + +/*********************************************************************** + * FILE_Fstat + * + * Stat a DOS handle. Return 1 if OK. + */ +int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize, + WORD *pdate, WORD *ptime ) +{ + struct stat st; + int handle; + + if ((handle = FILE_GetUnixHandle( hFile )) == -1) return 0; + if (fstat( handle, &st ) == -1) + { + FILE_SetDosError(); + return 0; + } + if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0); + if (psize) *psize = st.st_size; + DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime ); + return 1; +} + + +/*********************************************************************** + * FILE_MakeDir + */ +int FILE_MakeDir( LPCSTR path ) +{ + const char *unixName; + + dprintf_file(stddeb, "FILE_MakeDir: '%s'\n", path ); + + if ((unixName = DOSFS_IsDevice( path )) != NULL) + { + dprintf_file(stddeb, "FILE_MakeDir: device '%s'!\n", unixName); + DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk ); + return 0; + } + if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0; + if ((mkdir( unixName, 0777 ) == -1) && (errno != EEXIST)) + { + FILE_SetDosError(); + return 0; + } + return 1; +} + + +/*********************************************************************** + * FILE_RemoveDir + */ +int FILE_RemoveDir( LPCSTR path ) +{ + const char *unixName; + + dprintf_file(stddeb, "FILE_RemoveDir: '%s'\n", path ); + + if ((unixName = DOSFS_IsDevice( path )) != NULL) + { + dprintf_file(stddeb, "FILE_RemoveDir: device '%s'!\n", unixName); + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + return 0; + } + if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0; + if (rmdir( unixName ) == -1) + { + FILE_SetDosError(); + return 0; + } + return 1; +} + + +/*********************************************************************** + * FILE_Dup + * + * dup() function for DOS handles. + */ +HFILE FILE_Dup( HFILE hFile ) +{ + int handle, newhandle; + HFILE dosHandle; + + if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR; + if ((newhandle = dup(handle)) == -1) + { + FILE_SetDosError(); + return HFILE_ERROR; + } + if ((dosHandle = FILE_AllocTaskHandle( newhandle )) == HFILE_ERROR) + close( newhandle ); + return dosHandle; +} + + +/*********************************************************************** + * FILE_Dup2 + * + * dup2() function for DOS handles. + */ +HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 ) +{ + PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); + BYTE *files; + int handle, newhandle; + + if ((handle = FILE_GetUnixHandle( hFile1 )) == -1) return HFILE_ERROR; + if ((hFile2 < 0) || (hFile2 >= (INT)pdb->nbFiles)) + { + DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk ); + return HFILE_ERROR; + } + + if ((newhandle = dup(handle)) == -1) + { + FILE_SetDosError(); + return HFILE_ERROR; + } + if (newhandle >= 0xff) + { + DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk ); + close( newhandle ); + return HFILE_ERROR; + } + files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + if (files[hFile2] != 0xff) close( files[hFile2] ); + files[hFile2] = (BYTE)newhandle; + return hFile2; +} + + +/*********************************************************************** + * FILE_OpenFile + * + * Implementation of API function OpenFile(). Returns a Unix file handle. + */ +int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) +{ + const char *unixName, *dosName; + char *p; + int handle, len, i, unixMode; + struct stat st; + + ofs->cBytes = sizeof(OFSTRUCT); + ofs->nErrCode = 0; + if (mode & OF_REOPEN) name = ofs->szPathName; + dprintf_file( stddeb, "Openfile: %s %04x\n", name, mode ); + + /* OF_PARSE simply fills the structure */ + + if (mode & OF_PARSE) + { + if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) + { + ofs->nErrCode = DOS_ExtendedError; + return -1; + } + lstrcpyn( ofs->szPathName, dosName, sizeof(ofs->szPathName) ); + ofs->fFixedDisk = (GetDriveType( dosName[0]-'A' ) != DRIVE_REMOVABLE); + return 0; + } + + /* OF_CREATE is completely different from all other options, so + handle it first */ + + if (mode & OF_CREATE) + { + if ((unixName = DOSFS_GetUnixFileName( name, FALSE )) == NULL) + { + ofs->nErrCode = DOS_ExtendedError; + return -1; + } + dprintf_file( stddeb, "OpenFile: creating '%s'\n", unixName ); + handle = open( unixName, O_TRUNC | O_RDWR | O_CREAT, 0666 ); + if (handle == -1) + { + FILE_SetDosError(); + ofs->nErrCode = DOS_ExtendedError; + return -1; + } + lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ), + sizeof(ofs->szPathName) ); + return handle; + } + + /* Now look for the file */ + + /* First try the current directory */ + + lstrcpyn( ofs->szPathName, name, sizeof(ofs->szPathName) ); + if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL) + goto found; + + /* Now try some different paths if none was specified */ + + if ((mode & OF_SEARCH) && !(mode & OF_REOPEN)) + { + if (name[1] == ':') name += 2; + if ((p = strrchr( name, '\\' ))) name = p + 1; + if ((p = strrchr( name, '/' ))) name = p + 1; + if (!name[0]) goto not_found; + } + else + { + if ((name[1] == ':') || strchr( name, '/' ) || strchr( name, '\\' )) + goto not_found; + } + + if ((len = sizeof(ofs->szPathName) - strlen(name) - 1) < 0) goto not_found; + + /* Try the Windows directory */ + + GetWindowsDirectory( ofs->szPathName, len ); + strcat( ofs->szPathName, "\\" ); + strcat( ofs->szPathName, name ); + if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL) + goto found; + + /* Try the Windows system directory */ + + GetSystemDirectory( ofs->szPathName, len ); + strcat( ofs->szPathName, "\\" ); + strcat( ofs->szPathName, name ); + if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL) + goto found; + + /* Try the path of the current executable */ + + if (GetCurrentTask()) + { + GetModuleFileName( GetCurrentTask(), ofs->szPathName, len ); + if ((p = strrchr( ofs->szPathName, '\\' ))) + { + strcpy( p + 1, name ); + if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE ))) + goto found; + } + } + + /* Try all directories in path */ + + for (i = 0; ; i++) + { + if (!DIR_GetDosPath( i, ofs->szPathName, len )) break; + strcat( ofs->szPathName, "\\" ); + strcat( ofs->szPathName, name ); + if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE)) != NULL) + goto found; + } + +not_found: + dprintf_file( stddeb, "OpenFile: '%s' not found\n", name ); + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + ofs->nErrCode = ER_FileNotFound; + return -1; + +found: + dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName ); + lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE ), + sizeof(ofs->szPathName) ); + + if (mode & OF_PARSE) return 0; + + if (mode & OF_DELETE) + { + if (unlink( unixName ) == -1) goto not_found; + return 0; + } + + switch(mode & 3) + { + case OF_WRITE: + unixMode = O_WRONLY; break; + case OF_READWRITE: + unixMode = O_RDWR; break; + case OF_READ: + default: + unixMode = O_RDONLY; break; + } + + if ((handle = open( unixName, unixMode )) == -1) + { + if (Options.allowReadOnly && (unixMode == O_RDWR)) + { + if ((handle = open( unixName, O_RDONLY )) != -1) + fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", unixName ); + } + } + if (handle == -1) goto not_found; + + if (fstat( handle, &st ) != -1) + { + if ((mode & OF_VERIFY) && (mode & OF_REOPEN)) + { + if (memcmp( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) )) + return -1; + } + memcpy( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) ); + } + + if (mode & OF_EXIST) close( handle ); + + return handle; +} + + +/*********************************************************************** + * GetTempFileName (KERNEL.97) + */ +INT GetTempFileName( BYTE drive, LPCSTR prefix, UINT unique, LPSTR buffer ) +{ + int i, handle; + UINT num = unique ? (unique & 0xffff) : time(NULL) & 0xffff; + char *p; + + if (drive & TF_FORCEDRIVE) + { + sprintf( buffer, "%c:", drive & ~TF_FORCEDRIVE ); + } + else + { + DIR_GetTempDosDir( buffer, 132 ); /* buffer must be at least 144 */ + strcat( buffer, "\\" ); + } + + p = buffer + strlen(buffer); + for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++; + sprintf( p, "%04x.tmp", num ); + + if (unique) + { + lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 ); + dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer ); + return unique; + } + + /* Now try to create it */ + + do + { + if ((handle = FILE_Create( buffer, 0666, TRUE )) != -1) + { /* We created it */ + dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer ); + close( handle ); + break; + } + if (DOS_ExtendedError != ER_FileExists) break; /* No need to go on */ + num++; + sprintf( p, "%04x.tmp", num ); + } while (num != (unique & 0xffff)); + + lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 ); + dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer ); + return num; +} + + +/*********************************************************************** + * OpenFile (KERNEL.74) + */ +HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) +{ + int unixHandle; + HFILE handle; + + if ((unixHandle = FILE_OpenFile( name, ofs, mode )) == -1) + return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) + { + ofs->nErrCode = DOS_ExtendedError; + if (unixHandle) close( unixHandle ); + } + if (!unixHandle) FILE_FreeTaskHandle( handle ); + return handle; +} + + +/*********************************************************************** + * _lclose (KERNEL.81) + */ +HFILE _lclose( HFILE hFile ) +{ + int handle; + + dprintf_file( stddeb, "_lclose: handle %d\n", hFile ); + + if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR; + if (handle <= 2) + { + fprintf( stderr, "_lclose: internal error: closing handle %d\n", handle ); + exit(1); + } + FILE_FreeTaskHandle( hFile ); + close( handle ); + return 0; +} + + +/*********************************************************************** + * _lread (KERNEL.82) + */ +INT _lread( HFILE hFile, LPSTR buffer, WORD count ) +{ + return (INT)_hread( hFile, buffer, (LONG)count ); +} + + +/*********************************************************************** + * _lcreat (KERNEL.83) + */ +INT _lcreat( LPCSTR path, INT attr ) +{ + int unixHandle, mode; + HFILE handle; + + dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr ); + mode = (attr & 1) ? 0444 : 0666; + if ((unixHandle = FILE_Create( path, mode, FALSE )) == -1) + return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) + close( unixHandle ); + return handle; +} + + +/*********************************************************************** + * _lcreat_uniq (Not a Windows API) + */ +INT _lcreat_uniq( LPCSTR path, INT attr ) +{ + int unixHandle, mode; + HFILE handle; + + dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr ); + mode = (attr & 1) ? 0444 : 0666; + if ((unixHandle = FILE_Create( path, mode, TRUE )) == -1) + return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) + close( unixHandle ); + return handle; +} + + +/*********************************************************************** + * _llseek (KERNEL.84) + */ +LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin ) +{ + int handle, origin, result; + + dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n", + hFile, lOffset, nOrigin); + + if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR; + switch(nOrigin) + { + case 1: origin = SEEK_CUR; break; + case 2: origin = SEEK_END; break; + default: origin = SEEK_SET; break; + } + + if ((result = lseek( handle, lOffset, origin )) == -1) FILE_SetDosError(); + return (result == -1) ? HFILE_ERROR : result; +} + + +/*********************************************************************** + * _lopen (KERNEL.85) + */ +HFILE _lopen( LPCSTR path, INT mode ) +{ + int unixHandle; + int unixMode; + HFILE handle; + + dprintf_file(stddeb, "_lopen('%s',%04x)\n", path, mode ); + + switch(mode & 3) + { + case OF_WRITE: + unixMode = O_WRONLY | O_TRUNC; + break; + case OF_READWRITE: + unixMode = O_RDWR; + break; + case OF_READ: + default: + unixMode = O_RDONLY; + break; + } + if ((unixHandle = FILE_Open( path, unixMode )) == -1) return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) + close( unixHandle ); + return handle; +} + + +/*********************************************************************** + * _lwrite (KERNEL.86) + */ +INT _lwrite( HFILE hFile, LPCSTR buffer, WORD count ) +{ + return (INT)_hwrite( hFile, buffer, (LONG)count ); +} + + +/*********************************************************************** + * _hread (KERNEL.349) + */ +LONG _hread( HFILE hFile, LPSTR buffer, LONG count ) +{ + int handle; + LONG result; + + dprintf_file( stddeb, "_hread: %d %p %ld\n", hFile, buffer, count ); + + if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR; + if (!count) return 0; + if ((result = read( handle, buffer, count )) == -1) FILE_SetDosError(); + return (result == -1) ? HFILE_ERROR : result; +} + + +/*********************************************************************** + * _hwrite (KERNEL.350) + */ +LONG _hwrite( HFILE hFile, LPCSTR buffer, LONG count ) +{ + int handle; + LONG result; + + dprintf_file( stddeb, "_hwrite: %d %p %ld\n", hFile, buffer, count ); + + if ((handle = FILE_GetUnixHandle( hFile )) == -1) return HFILE_ERROR; + + if (count == 0) /* Expand or truncate at current position */ + result = ftruncate( handle, lseek( handle, 0, SEEK_CUR ) ); + else + result = write( handle, buffer, count ); + + if (result == -1) FILE_SetDosError(); + return (result == -1) ? HFILE_ERROR : result; +} + + +/*********************************************************************** + * SetHandleCount (KERNEL.199) + */ +WORD SetHandleCount( WORD count ) +{ + HANDLE hPDB = GetCurrentPDB(); + PDB *pdb = (PDB *)GlobalLock( hPDB ); + BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + WORD i; + + dprintf_file( stddeb, "SetHandleCount(%d)\n", count ); + + if (count < 20) count = 20; /* No point in going below 20 */ + else if (count > 254) count = 254; + + /* If shrinking the table, make sure all extra file handles are closed */ + if (count < pdb->nbFiles) + { + for (i = count; i < pdb->nbFiles; i++) + if (files[i] != 0xff) /* File open */ + { + DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, + SA_Abort, EL_Disk ); + return pdb->nbFiles; + } + } + + if (count == 20) + { + if (pdb->nbFiles > 20) + { + memcpy( pdb->fileHandles, files, 20 ); +#ifdef WINELIB + GlobalFree( pdb->fileHandlesPtr ); + pdb->fileHandlesPtr = pdb->fileHandles; +#else + GlobalFree( GlobalHandle( SELECTOROF(pdb->fileHandlesPtr) )); + pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18, + GlobalHandleToSel( hPDB ) ); +#endif + pdb->nbFiles = 20; + } + } + else /* More than 20, need a new file handles table */ + { + BYTE *newfiles; + HANDLE newhandle = GlobalAlloc( GMEM_MOVEABLE, count ); + if (!newhandle) + { + DOS_ERROR( ER_OutOfMemory, EC_OutOfResource, SA_Abort, EL_Memory ); + return pdb->nbFiles; + } + newfiles = (BYTE *)GlobalLock( newhandle ); + if (count > pdb->nbFiles) + { + memcpy( newfiles, files, pdb->nbFiles ); + memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles ); + } + else memcpy( newfiles, files, count ); +#ifdef WINELIB + if (pdb->nbFiles > 20) GlobalFree( pdb->fileHandlesPtr ); +#else + if (pdb->nbFiles > 20) + GlobalFree( GlobalHandle( SELECTOROF(pdb->fileHandlesPtr) )); +#endif + pdb->fileHandlesPtr = WIN16_GlobalLock( newhandle ); + pdb->nbFiles = count; + } + return pdb->nbFiles; +} diff --git a/if1632/Makefile.in b/if1632/Makefile.in index b8926e20f89..8cdd78d5212 100644 --- a/if1632/Makefile.in +++ b/if1632/Makefile.in @@ -51,4 +51,20 @@ call32.S: $(SPEC16_FILES) clean:: rm -f $(SPEC16_FILES) $(SPEC32_FILES) call32.S call16.S +# Kludge: don't use optimisation flags to compile these files +advapi32.o: advapi32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o advapi32.o advapi32.c +comdlg32.o: comdlg32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o comdlg32.o comdlg32.c +gdi32.o: gdi32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o gdi32.o gdi32.c +kernel32.o: kernel32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o kernel32.o kernel32.c +shell32.o: shell32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o shell32.o shell32.c +user32.o: user32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o user32.o user32.c +winprocs32.o: winprocs32.c + $(CC) -c $(DEFS) $(DIVINCL) $(EXTRA_DEFS) -o winprocs32.o winprocs32.c + ### Dependencies: diff --git a/if1632/callback.c b/if1632/callback.c index 2d6a742d150..27d236c510a 100644 --- a/if1632/callback.c +++ b/if1632/callback.c @@ -37,10 +37,12 @@ LONG CallWindowProc( WNDPROC func, HWND hwnd, WORD message, (hwnd,message,wParam,lParam); if(!a->win32) fprintf(stderr,"Where is the Win32 callback?\n"); - return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam); + if (UsesLParamPtr(message)) + return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam ? PTR_SEG_TO_LIN(lParam): 0); + else + return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam); } - /********************************************************************** * Catch (KERNEL.55) */ diff --git a/if1632/gdi.spec b/if1632/gdi.spec index 4249cbd605d..cd6027216f0 100644 --- a/if1632/gdi.spec +++ b/if1632/gdi.spec @@ -232,7 +232,7 @@ id 3 346 pascal16 SetTextAlign(word word) SetTextAlign 348 pascal16 Chord(word s_word s_word s_word s_word s_word s_word s_word s_word) Chord -349 pascal SetMapperFlags(word word) SetMapperFlags +349 pascal SetMapperFlags(word long) SetMapperFlags 350 pascal16 GetCharWidth(word word word ptr) GetCharWidth 351 pascal16 ExtTextOut(word s_word s_word word ptr ptr s_word ptr) ExtTextOut 352 stub GetPhysicalFontHandle diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec index 3ebcb860ca0..86bd082a710 100644 --- a/if1632/gdi32.spec +++ b/if1632/gdi32.spec @@ -11,7 +11,7 @@ base 1 0007 stub Arc 0008 stub ArcTo 0009 stub BeginPath -0010 stub BitBlt +0010 stdcall BitBlt(long long long long long long long long long) BitBlt 0011 stub CancelDC 0012 stub CheckColorsInGamut 0013 stub ChoosePixelFormat @@ -31,8 +31,8 @@ base 1 0027 stub CreateBrushIndirect 0028 stub CreateColorSpaceA 0029 stub CreateColorSpaceW -0030 stub CreateCompatibleBitmap -0031 stub CreateCompatibleDC +0030 stdcall CreateCompatibleBitmap(long long long) CreateCompatibleBitmap +0031 stdcall CreateCompatibleDC(long) CreateCompatibleDC 0032 stub CreateDCA 0033 stub CreateDCW 0034 stub CreateDIBPatternBrush @@ -50,13 +50,13 @@ base 1 0046 stub CreateFontW 0047 stub CreateHalftonePalette 0048 stub CreateHatchBrush -0049 stub CreateICA +0049 stdcall CreateICA(ptr ptr ptr ptr) CreateIC 0050 stub CreateICW 0051 stub CreateMetaFileA 0052 stub CreateMetaFileW 0053 stub CreatePalette 0054 stub CreatePatternBrush -0055 stub CreatePen +0055 stdcall CreatePen(long long long) CreatePen 0056 stub CreatePenIndirect 0057 stub CreatePolyPolygonRgn 0058 stub CreatePolygonRgn @@ -65,10 +65,10 @@ base 1 0061 stub CreateRoundRectRgn 0062 stub CreateScalableFontResourceA 0063 stub CreateScalableFontResourceW -0064 stub CreateSolidBrush +0064 stdcall CreateSolidBrush(long) CreateSolidBrush 0065 stub DPtoLP 0066 stub DeleteColorSpace -0067 stub DeleteDC +0067 stdcall DeleteDC(long) DeleteDC 0068 stub DeleteEnhMetaFile 0069 stub DeleteMetaFile 0070 stub DeleteObject @@ -172,7 +172,7 @@ base 1 0168 stub GetDCOrgEx 0169 stub GetDIBColorTable 0170 stub GetDIBits -0171 stub GetDeviceCaps +0171 stdcall GetDeviceCaps(long long) GetDeviceCaps 0172 stub GetDeviceGammaRamp 0173 stub GetETM 0174 stub GetEnhMetaFileA @@ -205,7 +205,7 @@ base 1 0201 stub GetMiterLimit 0202 stub GetNearestColor 0203 stub GetNearestPaletteIndex -0204 stub GetObjectA +0204 stdcall GetObjectA(long long ptr) GetObject 0205 stub GetObjectType 0206 stub GetObjectW 0207 stub GetOutlineTextMetricsA @@ -233,7 +233,7 @@ base 1 0229 stub GetTextExtentExPointW 0230 stub GetTextExtentPoint32A 0231 stub GetTextExtentPoint32W -0232 stub GetTextExtentPointA +0232 stdcall GetTextExtentPointA(long ptr long ptr) GetTextExtentPoint 0233 stub GetTextExtentPointW 0234 stub GetTextFaceA 0235 stub GetTextFaceW @@ -250,18 +250,18 @@ base 1 0246 stub InvertRgn 0247 stub LPtoDP 0248 stub LineDDA -0249 stub LineTo +0249 stdcall LineTo(long long long) LineTo 0250 stub LoadImageColorMatcherA 0251 stub LoadImageColorMatcherW 0252 stub MaskBlt 0253 stub ModifyWorldTransform -0254 stub MoveToEx +0254 stdcall MoveToEx(long long long ptr) MoveToEx 0255 stub OffsetClipRgn 0256 stub OffsetRgn 0257 stub OffsetViewportOrgEx 0258 stub OffsetWindowOrgEx 0259 stub PaintRgn -0260 stub PatBlt +0260 stdcall PatBlt(long long long long long long) PatBlt 0261 stub PathToRegion 0262 stub Pie 0263 stub PlayEnhMetaFile @@ -300,13 +300,13 @@ base 1 0296 stub SelectClipPath 0297 stub SelectClipRgn 0298 stub SelectFontLocal -0299 stub SelectObject +0299 stdcall SelectObject(long long) SelectObject 0300 stub SelectPalette 0301 stub SetAbortProc 0302 stub SetArcDirection 0303 stub SetBitmapBits 0304 stub SetBitmapDimensionEx -0305 stub SetBkColor +0305 stdcall SetBkColor(long long) SetBkColor 0306 stub SetBkMode 0307 stub SetBoundsRect 0308 stub SetBrushOrgEx @@ -339,7 +339,7 @@ base 1 0335 stub SetSystemPaletteUse 0336 stub SetTextAlign 0337 stub SetTextCharacterExtra -0338 stub SetTextColor +0338 stdcall SetTextColor(long long) SetTextColor 0339 stub SetTextJustification 0340 stub SetViewportExtEx 0341 stub SetViewportOrgEx diff --git a/if1632/kernel.spec b/if1632/kernel.spec index 2899a60e9b2..d4e789857ad 100644 --- a/if1632/kernel.spec +++ b/if1632/kernel.spec @@ -80,7 +80,7 @@ id 1 81 pascal16 _lclose(word) _lclose 82 pascal16 _lread(word ptr word) _lread 83 pascal16 _lcreat(ptr word) _lcreat -84 pascal _llseek(word long word) _llseek +84 pascal _llseek(word long word) _llseek 85 pascal16 _lopen(ptr word) _lopen 86 pascal16 _lwrite(word ptr word) _lwrite 87 pascal16 RESERVED5(ptr ptr) lstrcmp @@ -103,7 +103,7 @@ id 1 104 stub GetCodeInfo 105 stub GetExeVersion 106 pascal SetSwapAreaSize(word) SetSwapAreaSize -107 pascal SetErrorMode(word) SetErrorMode +107 pascal16 SetErrorMode(word) SetErrorMode 108 stub SwitchStackTo 109 stub SwitchStackBack 110 pascal16 PatchCodeHandle(word) PatchCodeHandle @@ -205,15 +205,15 @@ id 1 205 stub CVWBreak 206 pascal16 AllocSelectorArray(word) AllocSelectorArray 207 return IsDBCSLeadByte 2 0 -216 stub RegEnumKey -217 stub RegOpenKey -218 stub RegCreateKey +216 pascal RegEnumKey(long long ptr long) RegEnumKey +217 pascal RegOpenKey(long ptr ptr) RegOpenKey +218 pascal RegCreateKey(long ptr ptr) RegCreateKey 219 stub RegDeleteValue -220 stub RegCloseKey -221 stub RegSetValue +220 pascal RegCloseKey(long) RegCloseKey +221 pascal RegSetValue(long ptr long ptr long) RegSetValue 222 stub RegDeleteValue 223 stub RegEnumValue -224 stub RegQueryValue +224 pascal RegQueryValue(long ptr ptr ptr) RegQueryValue 225 stub RegQueryValueEx 226 stub RegSetValueEx 227 stub RegFlushKey @@ -255,9 +255,9 @@ id 1 345 stub IsSharedSelector 346 pascal16 IsBadHugeReadPtr(segptr long) IsBadHugeReadPtr 347 pascal16 IsBadHugeWritePtr(segptr long) IsBadHugeWritePtr -348 pascal hmemcpy(ptr ptr long) hmemcpy -349 pascal _hread(word ptr long) _hread -350 pascal _hwrite(word ptr long) _hwrite +348 pascal16 hmemcpy(ptr ptr long) hmemcpy +349 pascal _hread(word ptr long) _hread +350 pascal _hwrite(word ptr long) _hwrite #351 BUNNY_351 352 stub lstrcatn 353 pascal lstrcpyn(segptr segptr word) WIN16_lstrcpyn diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec index e7d35234056..b1c7193c103 100644 --- a/if1632/kernel32.spec +++ b/if1632/kernel32.spec @@ -129,7 +129,7 @@ base 1 0125 stub FindNextChangeNotification 0126 stub FindNextFileA 0127 stub FindNextFileW -0128 stub FindResourceA +0128 stdcall FindResourceA(long ptr ptr) FindResource32 0129 stub FindResourceExA 0130 stub FindResourceExW 0131 stub FindResourceW @@ -146,7 +146,7 @@ base 1 0142 stub FreeEnvironmentStringsW 0143 stub FreeLibrary 0144 stub FreeLibraryAndExitThread -0145 stub FreeResource +0145 stdcall FreeResource(long) FreeResource32 0146 stub FreeVirtualBuffer 0147 stub GenerateConsoleCtrlEvent 0148 stdcall GetACP() GetACP @@ -252,13 +252,13 @@ base 1 0248 stdcall GetOEMCP() GetOEMCP 0249 stub GetOverlappedResult 0250 stub GetPriorityClass -0251 stub GetPrivateProfileIntA +0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt 0252 stub GetPrivateProfileIntW 0253 stub GetPrivateProfileSectionA 0254 stub GetPrivateProfileSectionW 0255 stub GetPrivateProfileStringA 0256 stub GetPrivateProfileStringW -0257 stub GetProcAddress +0257 stdcall GetProcAddress(long long) WIN32_GetProcAddress 0258 stub GetProcessAffinityMask 0259 return GetProcessHeap 0 0 0260 stub GetProcessHeaps @@ -336,7 +336,7 @@ base 1 0331 stub GlobalUnfix 0332 stub GlobalUnlock 0333 stub GlobalWire -0334 stub HeapAlloc +0334 stdcall HeapAlloc(long long long) HeapAlloc 0335 stub HeapCompact 0336 stub HeapCreate 0337 stub HeapDestroy @@ -367,12 +367,12 @@ base 1 0362 stub LCMapStringA 0363 stub LCMapStringW 0364 stub LeaveCriticalSection -0365 stub LoadLibraryA +0365 stdcall LoadLibraryA(long) LoadLibraryA 0366 stub LoadLibraryExA 0367 stub LoadLibraryExW 0368 stub LoadLibraryW 0369 stub LoadModule -0370 stub LoadResource +0370 stdcall LoadResource(long long) LoadResource32 0371 stdcall LocalAlloc(long long) GlobalAlloc32 0372 stub LocalCompact 0373 stub LocalFileTimeToFileTime @@ -420,7 +420,7 @@ base 1 0415 stub QueryPerformanceCounter 0416 stub QueryPerformanceFrequency 0417 stub QueryWin31IniFilesMappedToRegistry -0418 stub RaiseException +0418 stdcall RaiseException(long long long ptr) RaiseException 0419 stub ReadConsoleA 0420 stub ReadConsoleInputA 0421 stub ReadConsoleInputW @@ -496,7 +496,7 @@ base 1 0491 stub SetFileAttributesW 0492 stdcall SetFilePointer(long long ptr long) SetFilePointer 0493 stub SetFileTime -0494 stub SetHandleCount +0494 stdcall SetHandleCount(long) W32_SetHandleCount 0495 stub SetHandleInformation 0496 stub SetLastConsoleEventActive 0497 stdcall SetLastError(long) SetLastError diff --git a/if1632/relay32.c b/if1632/relay32.c index 67c64617361..7da3a475181 100644 --- a/if1632/relay32.c +++ b/if1632/relay32.c @@ -15,8 +15,8 @@ #include "pe_image.h" #include "peexe.h" #include "relay32.h" +#include "xmalloc.h" #include "stddebug.h" -/* #define DEBUG_RELAY */ #include "debug.h" WIN32_builtin *WIN32_builtin_list; @@ -54,7 +54,7 @@ WIN32_builtin *RELAY32_GetBuiltinDLL(char *name) len = (cp=strchr(name,'.')) ? (cp-name) : strlen(name); for(it=WIN32_builtin_list;it;it=it->next) - if(strncasecmp(name,it->name,len)==0) + if(lstrncmpi(name,it->name,len)==0) return it; return NULL; } @@ -78,19 +78,22 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint) int i; u_short * ordinal; u_long * function; - u_char ** name, *ename; + u_char ** name; struct PE_Export_Directory * pe_exports; unsigned int load_addr; dprintf_module(stddeb, "Looking for %s in %s, hint %x\n", item ? item: "(no name)", dll_name, hint); dll=RELAY32_GetBuiltinDLL(dll_name); + /* This should deal with built-in DLLs only. See pe_module on loading + PE DLLs */ +#if 0 if(!dll) { if(!wine_files || !wine_files->name || - strcasecmp(dll_name, wine_files->name)) { + lstrcmpi(dll_name, wine_files->name)) { LoadModule(dll_name, (LPVOID) -1); if(!wine_files || !wine_files->name || - strcasecmp(dll_name, wine_files->name)) + lstrcmpi(dll_name, wine_files->name)) return 0; } load_addr = wine_files->load_addr; @@ -118,7 +121,7 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint) #if 0 if(hint && hintsize && !dll->functions[hint].name) { - dll->functions[hint].name=strdup(item); + dll->functions[hint].name=xstrdup(item); dprintf_module(stddeb, "Returning unimplemented function %s.%d\n", dll_name,hint); return dll->functions[hint].definition; @@ -127,6 +130,7 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint) printf("Not found\n"); return 0; } +#endif /* import by ordinal */ if(!item){ if(hint && hintsize)return dll->functions[hint].definition; @@ -145,12 +149,11 @@ void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint) /* function at hint has no name (unimplemented) */ if(hint && hintsize && !dll->functions[hint].name) { - dll->functions[hint].name=strdup(item); + dll->functions[hint].name=xstrdup(item); dprintf_module(stddeb, "Returning unimplemented function %s.%d\n", dll_name,hint); return dll->functions[hint].definition; } - printf("Not found\n"); return 0; } diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec index 3a45fda47d2..9bfe141b23f 100644 --- a/if1632/toolhelp.spec +++ b/if1632/toolhelp.spec @@ -31,7 +31,7 @@ id 12 77 stub TERMINATEAPP 78 pascal MemoryRead(word long ptr long) MemoryRead 79 pascal MemoryWrite(word long ptr long) MemoryWrite -80 stub TIMERCOUNT +80 pascal16 TimerCount(ptr) TimerCount 81 stub TASKSETCSIP 82 stub TASKGETCSIP 83 stub TASKSWITCH diff --git a/if1632/user32.spec b/if1632/user32.spec index c525e30906d..50f41ee71cf 100644 --- a/if1632/user32.spec +++ b/if1632/user32.spec @@ -46,7 +46,7 @@ base 1 0042 stub CharUpperBuffW 0043 stub CharUpperW 0044 stub CheckDlgButton -0045 stub CheckMenuItem +0045 stdcall CheckMenuItem(long long long) CheckMenuItem 0046 stub CheckMenuRadioItem 0047 stub CheckRadioButton 0048 stub ChildWindowFromPoint @@ -162,10 +162,10 @@ base 1 0157 stub DrawFrameControl 0158 stub DrawIcon 0159 stub DrawIconEx -0160 stub DrawMenuBar +0160 stdcall DrawMenuBar(long) DrawMenuBar 0161 stub DrawStateA 0162 stub DrawStateW -0163 stub DrawTextA +0163 stdcall DrawTextA(long ptr long ptr long) DrawText 0164 stub DrawTextExA 0165 stub DrawTextExW 0166 stub DrawTextW @@ -221,7 +221,7 @@ base 1 0216 stub GetClassNameA 0217 stub GetClassNameW 0218 stub GetClassWord -0219 stub GetClientRect +0219 stdcall GetClientRect(long long) GetClientRect 0220 stub GetClipCursor 0221 stub GetClipboardData 0222 stub GetClipboardFormatNameA @@ -231,7 +231,7 @@ base 1 0226 stub GetCursor 0227 stub GetCursorInfo 0228 stub GetCursorPos -0229 stub GetDC +0229 stdcall GetDC(long) GetDC 0230 stub GetDCEx 0231 stub GetDesktopWindow 0232 stub GetDialogBaseUnits @@ -258,7 +258,7 @@ base 1 0253 stub GetKeyboardState 0254 stub GetKeyboardType 0255 stub GetLastActivePopup -0256 stub GetMenu +0256 stdcall GetMenu(long) GetMenu 0257 stub GetMenuCheckMarkDimensions 0258 stub GetMenuContextHelpId 0259 stub GetMenuDefaultItem @@ -293,7 +293,7 @@ base 1 0288 stdcall GetSysColor(long) GetSysColor 0289 stub GetSysColorBrush 0290 stub GetSystemMenu -0291 stub GetSystemMetrics +0291 stdcall GetSystemMetrics(long) GetSystemMetrics 0292 stub GetTabbedTextExtentA 0293 stub GetTabbedTextExtentW 0294 stub GetThreadDesktop @@ -305,7 +305,7 @@ base 1 0300 stub GetUserObjectSecurity 0301 stub GetWindow 0302 stub GetWindowContextHelpId -0303 stub GetWindowDC +0303 stdcall GetWindowDC(long) GetWindowDC 0304 stub GetWindowLongA 0305 stub GetWindowLongW 0306 stub GetWindowPlacement @@ -346,7 +346,7 @@ base 1 0341 stub IsDialogMessageA 0342 stub IsDialogMessageW 0343 stub IsDlgButtonChecked -0344 stub IsIconic +0344 stdcall IsIconic(long) IsIconic 0345 stub IsMenu 0346 stub IsRectEmpty 0347 stub IsWindow @@ -356,16 +356,17 @@ base 1 0351 stub IsZoomed 0352 stub KillSystemTimer 0353 stub KillTimer -0354 stdcall LoadAcceleratorsA(long ptr) LoadAccelerators +0354 stdcall LoadAcceleratorsA(long ptr) LoadAccelerators32 0355 stub LoadAcceleratorsW -0356 stdcall LoadBitmapA(long ptr) LoadBitmap +0356 stdcall LoadBitmapA(long ptr) LoadBitmapA32 +0357 stdcall LoadBitmapW(long ptr) LoadBitmapW32 0357 stub LoadBitmapW 0358 stdcall LoadCursorA(long ptr) LoadCursor 0359 stub LoadCursorFromFileA 0360 stub LoadCursorFromFileW 0361 stub LoadCursorW -0362 stdcall LoadIconA(long ptr) LoadIcon -0363 stub LoadIconW +0362 stdcall LoadIconA(long ptr) LoadIconA32 +0363 stdcall LoadIconW(long ptr) LoadIconW32 0364 stub LoadImageA 0365 stub LoadImageW 0366 stub LoadKeyboardLayoutA @@ -376,8 +377,8 @@ base 1 0371 stub LoadMenuIndirectW 0372 stub LoadMenuW 0373 stub LoadRemoteFonts -0374 stdcall LoadStringA(long long ptr long) LoadString -0375 stub LoadStringW +0374 stdcall LoadStringA(long long ptr long) LoadStringA32 +0375 stdcall LoadStringW(long long ptr long) LoadString32 0376 stub LockWindowStation 0377 stub LockWindowUpdate 0378 stub LookupIconIdFromDirectory @@ -422,7 +423,7 @@ base 1 0417 stub PlaySoundEvent 0418 stub PostMessageA 0419 stub PostMessageW -0420 stub PostQuitMessage +0420 stdcall PostQuitMessage(long) PostQuitMessage 0421 stub PostThreadMessageA 0422 stub PostThreadMessageW 0423 stub PtInRect @@ -441,7 +442,7 @@ base 1 0436 stub RegisterWindowMessageA 0437 stub RegisterWindowMessageW 0438 stub ReleaseCapture -0439 stub ReleaseDC +0439 stdcall ReleaseDC(long long) ReleaseDC 0440 stub RemoveMenu 0441 stub RemovePropA 0442 stub RemovePropW @@ -531,7 +532,7 @@ base 1 0526 stub SetWindowsHookExW 0527 stub SetWindowsHookW 0528 stub ShowCaret -0529 stub ShowCursor +0529 stdcall ShowCursor(long) ShowCursor 0530 stub ShowOwnedPopups 0531 stub ShowScrollBar 0532 stub ShowStartGlass @@ -553,11 +554,11 @@ base 1 0548 stub TrackPopupMenu 0549 stub TrackPopupMenuEx 0550 stub TranslateAccelerator -0551 stub TranslateAcceleratorA +0551 stdcall TranslateAcceleratorA(long long ptr) TranslateAccelerator 0552 stub TranslateAcceleratorW 0553 stub TranslateCharsetInfo 0554 stub TranslateMDISysAccel -0555 stub TranslateMessage +0555 stdcall TranslateMessage(ptr) USER32_TranslateMessage 0556 stub UnhookWindowsHook 0557 stub UnhookWindowsHookEx 0558 stub UnionRect diff --git a/if1632/winprocs32.spec b/if1632/winprocs32.spec index 9789e8a3d8b..6bb7b0b34d0 100644 --- a/if1632/winprocs32.spec +++ b/if1632/winprocs32.spec @@ -1,25 +1,25 @@ name winprocs32 -1 stdcall ButtonWndProc(long long long long) ButtonWndProc -2 stdcall StaticWndProc(long long long long) StaticWndProc -3 stdcall ScrollBarWndProc(long long long long) ScrollBarWndProc -4 stdcall ListBoxWndProc(long long long long) ListBoxWndProc -5 stdcall ComboBoxWndProc(long long long long) ComboBoxWndProc -6 stdcall EditWndProc(long long long long) EditWndProc -7 stdcall PopupMenuWndProc(long long long long) PopupMenuWndProc -8 stdcall DesktopWndProc(long long long long) DesktopWndProc -9 stdcall DefDlgProc(long long long long) DefDlgProc -10 stdcall MDIClientWndProc(long long long long) MDIClientWndProc -11 stdcall DefWindowProc(long long long long) DefWindowProc -12 stdcall DefMDIChildProc(long long long long) DefMDIChildProc -13 stdcall SystemMessageBoxProc(long long long long) SystemMessageBoxProc -14 stdcall FileOpenDlgProc(long long long long) FileOpenDlgProc -15 stdcall FileSaveDlgProc(long long long long) FileSaveDlgProc -16 stdcall ColorDlgProc(long long long long) ColorDlgProc -17 stdcall FindTextDlgProc(long long long long) FindTextDlgProc -18 stdcall ReplaceTextDlgProc(long long long long) ReplaceTextDlgProc -19 stdcall PrintSetupDlgProc(long long long long) PrintSetupDlgProc -20 stdcall PrintDlgProc(long long long long) PrintDlgProc -21 stdcall AboutDlgProc(long long long long) AboutDlgProc -22 stdcall ComboLBoxWndProc(long long long long) ComboLBoxWndProc +1 stdcall ButtonWndProc(long long long long) ButtonWndProc32 +2 stdcall StaticWndProc(long long long long) StaticWndProc32 +3 stdcall ScrollBarWndProc(long long long long) ScrollBarWndProc32 +4 stdcall ListBoxWndProc(long long long long) ListBoxWndProc32 +5 stdcall ComboBoxWndProc(long long long long) ComboBoxWndProc32 +6 stdcall EditWndProc(long long long long) EditWndProc32 +7 stdcall PopupMenuWndProc(long long long long) PopupMenuWndProc32 +8 stdcall DesktopWndProc(long long long long) DesktopWndProc32 +9 stdcall DefDlgProc(long long long long) DefDlgProc32 +10 stdcall MDIClientWndProc(long long long long) MDIClientWndProc32 +11 stdcall DefWindowProc(long long long long) DefWindowProc32 +12 stdcall DefMDIChildProc(long long long long) DefMDIChildProc32 +13 stdcall SystemMessageBoxProc(long long long long) SystemMessageBoxProc32 +14 stdcall FileOpenDlgProc(long long long long) FileOpenDlgProc32 +15 stdcall FileSaveDlgProc(long long long long) FileSaveDlgProc32 +16 stdcall ColorDlgProc(long long long long) ColorDlgProc32 +17 stdcall FindTextDlgProc(long long long long) FindTextDlgProc32 +18 stdcall ReplaceTextDlgProc(long long long long) ReplaceTextDlgProc32 +19 stdcall PrintSetupDlgProc(long long long long) PrintSetupDlgProc32 +20 stdcall PrintDlgProc(long long long long) PrintDlgProc32 +21 stdcall AboutDlgProc(long long long long) AboutDlgProc32 +22 stdcall ComboLBoxWndProc(long long long long) ComboLBoxWndProc32 23 stdcall CARET_Callback(long long long long) CARET_Callback diff --git a/include/arch.h b/include/arch.h index be237faba2f..fc7c5cb1fe5 100644 --- a/include/arch.h +++ b/include/arch.h @@ -6,8 +6,8 @@ #if defined (mc68000) || defined (sparc) -#define CONV_LONG(a) (((a)&0xFF) << 24) | (((a) & 0xFF00) << 8) | (((unsigned long)(a) & 0xFF0000) >> 8) | ((unsigned long)((a)&0xFF000000) >> 24) -#define CONV_SHORT(a) (((a) & 0xFF) << 8) | (((unsigned long)(a) & 0xFF00) >> 8) +#define CONV_LONG(a) (((int)(a)&0xFF) << 24) | (((int)(a) & 0xFF00) << 8) | (((unsigned long)(a) & 0xFF0000) >> 8) | (((unsigned long)(a)&0xFF000000) >> 24) +#define CONV_SHORT(a) (((int)(a) & 0xFF) << 8) | (((unsigned long)(a) & 0xFF00) >> 8) #define CONV_CHAR_TO_LONG(x) ((unsigned long)(x) >> 24) #define CONV_SHORT_TO_LONG(x) ((unsigned long)(x) >> 16) diff --git a/include/directory.h b/include/directory.h new file mode 100644 index 00000000000..c466af8624c --- /dev/null +++ b/include/directory.h @@ -0,0 +1,18 @@ +/* + * DOS directory handling declarations + * + * Copyright 1996 Alexandre Julliard + */ + +#ifndef __WINE_DIRECTORY_H +#define __WINE_DIRECTORY_H + +extern int DIR_Init(void); +extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count ); +extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count ); +extern UINT DIR_GetTempUnixDir( LPSTR path, UINT count ); +extern UINT DIR_GetTempDosDir( LPSTR path, UINT count ); +extern UINT DIR_GetDosPath( int element, LPSTR path, UINT count ); +extern UINT DIR_GetUnixPath( int element, LPSTR path, UINT count ); + +#endif /* __WINE_DIRECTORY_H */ diff --git a/include/dos_fs.h b/include/dos_fs.h index 1200dfd52d9..2bcca390f81 100644 --- a/include/dos_fs.h +++ b/include/dos_fs.h @@ -1,37 +1,42 @@ +/* + * DOS file system declarations + * + * Copyright 1996 Alexandre Julliard + */ + #ifndef __WINE_DOS_FS_H #define __WINE_DOS_FS_H -#include +#include +#include "wintypes.h" + +#define MAX_FILENAME_LEN 256 +#define MAX_PATHNAME_LEN 1024 + +typedef struct +{ + char name[12]; /* File name in FCB format */ + char unixname[MAX_FILENAME_LEN]; /* Unix file name */ + DWORD size; /* File size in bytes */ + WORD date; /* File date in DOS format */ + WORD time; /* File time in DOS format */ + BYTE attr; /* File DOS attributes */ +} DOS_DIRENT; + +#define IS_END_OF_NAME(ch) (!(ch) || ((ch) == '/') || ((ch) == '\\')) + +extern void DOSFS_ToDosDateTime( time_t *unixtime, WORD *pDate, WORD *pTime ); +extern const char *DOSFS_ToDosFCBFormat( const char *name ); +extern const char *DOSFS_ToDosDTAFormat( const char *name ); +extern const char *DOSFS_IsDevice( const char *name ); +extern const char * DOSFS_GetUnixFileName( const char * name, int check_last ); +extern const char * DOSFS_GetDosTrueName( const char *name, int unix_format ); +extern int DOSFS_GetDosFileName( const char *name, char *buffer, int len ); +extern int DOSFS_FindNext( const char *path, const char *mask, int drive, + BYTE attr, int skip, DOS_DIRENT *entry ); + -extern void DOS_InitFS(void); -extern WORD DOS_GetEquipment(void); -extern int DOS_ValidDrive(int drive); -extern int DOS_GetDefaultDrive(void); -extern void DOS_SetDefaultDrive(int drive); -extern void ToUnix(char *s); -extern void ToDos(char *s); -extern int DOS_DisableDrive(int drive); -extern int DOS_EnableDrive(int drive); -extern char *DOS_GetUnixFileName(const char *dosfilename); -extern char *DOS_GetDosFileName(char *unixfilename); -extern char *DOS_GetCurrentDir(int drive); -extern int DOS_ChangeDir(int drive, char *dirname); -extern int DOS_MakeDir(int drive, char *dirname); -extern int DOS_GetSerialNumber(int drive, unsigned long *serialnumber); -extern int DOS_SetSerialNumber(int drive, unsigned long serialnumber); -extern char *DOS_GetVolumeLabel(int drive); -extern int DOS_SetVolumeLabel(int drive, char *label); extern int DOS_GetFreeSpace(int drive, long *size, long *available); -extern char *DOS_FindFile(char *buffer, int buflen, const char *rootname, char **extensions, char *path); extern char *WineIniFileName(void); -extern char *WinIniFileName(void); -extern struct dosdirent *DOS_opendir(char *dosdirname); -extern struct dosdirent *DOS_readdir(struct dosdirent *de); -extern void DOS_closedir(struct dosdirent *de); -extern char *DOS_GetRedirectedDir(int drive); -extern void errno_to_doserr(void); -extern int DOS_Error(int extended, int class, int locus); - -extern char WindowsPath[256]; #endif /* __WINE_DOS_FS_H */ diff --git a/include/drive.h b/include/drive.h new file mode 100644 index 00000000000..ab9fa9d9dc0 --- /dev/null +++ b/include/drive.h @@ -0,0 +1,29 @@ +/* + * DOS drive handling declarations + * + * Copyright 1995 Alexandre Julliard + */ + +#ifndef __WINE_DRIVE_H +#define __WINE_DRIVE_H + +#include "wintypes.h" + +#define MAX_DOS_DRIVES 26 + +extern int DRIVE_Init(void); +extern int DRIVE_IsValid( int drive ); +extern int DRIVE_GetCurrentDrive(void); +extern int DRIVE_SetCurrentDrive( int drive ); +extern int DRIVE_FindDriveRoot( const char **path ); +extern const char * DRIVE_GetRoot( int drive ); +extern const char * DRIVE_GetDosCwd( int drive ); +extern const char * DRIVE_GetUnixCwd( int drive ); +extern const char * DRIVE_GetLabel( int drive ); +extern DWORD DRIVE_GetSerialNumber( int drive ); +extern int DRIVE_SetSerialNumber( int drive, DWORD serial ); +extern int DRIVE_Chdir( int drive, const char *path ); +extern int DRIVE_Disable( int drive ); +extern int DRIVE_Enable( int drive ); + +#endif /* __WINE_DRIVE_H */ diff --git a/include/file.h b/include/file.h new file mode 100644 index 00000000000..1c585a4eff4 --- /dev/null +++ b/include/file.h @@ -0,0 +1,29 @@ +/* + * File handling declarations + * + * Copyright 1996 Alexandre Julliard + */ + +#ifndef __WINE_FILE_H +#define __WINE_FILE_H + +#include "windows.h" + +extern void FILE_SetDosError(void); +extern int FILE_GetUnixHandle( HFILE handle ); +extern void FILE_CloseAllFiles( HANDLE hPDB ); +extern int FILE_Open( LPCSTR path, int mode ); +extern int FILE_Create( LPCSTR path, int mode, int unique ); +extern int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize, + WORD *pdate, WORD *ptime ); +extern int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize, + WORD *pdate, WORD *ptime ); +extern int FILE_Unlink( LPCSTR path ); +extern int FILE_MakeDir( LPCSTR path ); +extern int FILE_RemoveDir( LPCSTR path ); +extern HFILE FILE_Dup( HFILE hFile ); +extern HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 ); +extern int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ); +extern INT _lcreat_uniq( LPCSTR path, INT attr ); + +#endif /* __WINE_FILE_H */ diff --git a/include/kernel32.h b/include/kernel32.h index 367a6399c19..ecb4fc60945 100644 --- a/include/kernel32.h +++ b/include/kernel32.h @@ -14,6 +14,7 @@ DWORD ErrnoToLastError(int errno_num); /* Linux's wchar_t is unsigned long but Win32 wants unsigned short */ typedef unsigned short WCHAR; +typedef WCHAR *LPTSTR; /* Code page information. */ diff --git a/include/menu.h b/include/menu.h index 59f292df5c8..5a25e1e7172 100644 --- a/include/menu.h +++ b/include/menu.h @@ -15,8 +15,6 @@ extern void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt ); /* menu.c */ extern void MENU_TrackKbdMenuBar( HWND hwnd, UINT wParam ); /* menu.c */ extern UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, BOOL suppress_draw ); /* menu.c */ -extern HMENU CopySysMenu(); /* menu.c */ - extern LRESULT PopupMenuWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam ); typedef struct tagMENUITEM diff --git a/include/message.h b/include/message.h index 85159b0d960..bf242b7f299 100644 --- a/include/message.h +++ b/include/message.h @@ -63,6 +63,8 @@ typedef struct tagMESSAGEQUEUE #pragma pack(4) #endif +extern DWORD MSG_WineStartTicks; /* Ticks at Wine startup */ + extern void MSG_IncPaintCount( HANDLE hQueue ); extern void MSG_DecPaintCount( HANDLE hQueue ); extern void MSG_IncTimerCount( HANDLE hQueue ); diff --git a/include/module.h b/include/module.h index 3ca58cc4150..16417541e09 100644 --- a/include/module.h +++ b/include/module.h @@ -112,6 +112,7 @@ typedef struct extern BOOL MODULE_Init(void); extern int MODULE_OpenFile( HMODULE hModule ); extern LPSTR MODULE_GetModuleName( HMODULE hModule ); +extern void MODULE_RegisterModule( HMODULE hModule ); extern WORD MODULE_GetOrdinal( HMODULE hModule, char *name ); extern SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal ); extern BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset ); diff --git a/include/msdos.h b/include/msdos.h index 5964d82556c..e399be1ae7b 100644 --- a/include/msdos.h +++ b/include/msdos.h @@ -32,6 +32,22 @@ struct fcb { BYTE dummy2[9]; }; +/* DTA layout for FindFirst/FindNext */ +typedef struct +{ + BYTE drive; /* 00 drive letter */ + char mask[11]; /* 01 search template */ + BYTE search_attr; /* 0c search attributes */ + WORD count WINE_PACKED; /* 0d entry count within directory */ + WORD cluster WINE_PACKED; /* 0f cluster of parent directory */ + char *unixPath WINE_PACKED; /* 11 unix path (was: reserved) */ + BYTE fileattr; /* 15 file attributes */ + WORD filetime; /* 16 file time */ + WORD filedate; /* 18 file date */ + DWORD filesize WINE_PACKED; /* 1a file size */ + char filename[13]; /* 1e file name + extension */ +} FINDFILE_DTA; + #define DOSVERSION 0x1606 /* Major version in low byte: DOS 6.22 */ #define WINDOSVER 0x0616 /* Windows reports the DOS version reversed */ @@ -48,89 +64,94 @@ extern struct DosDeviceStruct LPT[MAX_PORTS]; *((BYTE*)((a)+1)) = ((b)>>8) & 0xff;\ } while(0) -#define setdword(a,b) do { *(BYTE*)(a) = (b) & 0xff; \ - *((BYTE*)(a)+1) = ((b)>>8) & 0xff; \ - *((BYTE*)(a)+2) = ((b)>>16) & 0xff; \ - *((BYTE*)(a)+3) = ((b)>>24) & 0xff; \ - } while(0) - -#define getword(a) ( (WORD)*(BYTE*)(a) + \ - ((WORD)*((BYTE*)(a) + 1) << 8)) - -#define getdword(a) ( (DWORD)*(BYTE*)(a) + \ - (DWORD)(*((BYTE*)(a) + 1) << 8) + \ - (DWORD)(*((BYTE*)(a) + 2) << 16) + \ - (DWORD)(*((BYTE*)(a) + 3) << 24)) /* dos file attributes */ -#define FA_NORMAL 0x00 /* Normal file, no attributes */ -#define FA_RDONLY 0x01 /* Read only attribute */ -#define FA_HIDDEN 0x02 /* Hidden file */ -#define FA_SYSTEM 0x04 /* System file */ -#define FA_LABEL 0x08 /* Volume label */ -#define FA_DIREC 0x10 /* Directory */ -#define FA_ARCH 0x20 /* Archive */ +#define FA_NORMAL 0x00 /* Normal file, no attributes */ +#define FA_RDONLY 0x01 /* Read only attribute */ +#define FA_HIDDEN 0x02 /* Hidden file */ +#define FA_SYSTEM 0x04 /* System file */ +#define FA_LABEL 0x08 /* Volume label */ +#define FA_DIRECTORY 0x10 /* Directory */ +#define FA_ARCHIVE 0x20 /* Archive */ +#define FA_UNUSED 0x40 /* Unused */ -/* extended error codes */ -#define NoError 0x00 -#define InvalidFunction 0x01 -#define FileNotFound 0x02 -#define PathNotFound 0x03 -#define AccessDenied 0x05 -#define InvalidHandle 0x06 -#define MCBDestroyed 0x07 -#define OutOfMemory 0x08 -#define MCBInvalid 0x09 -#define DataInvalid 0x0d -#define InvalidDrive 0x0f -#define CanNotRemoveCwd 0x10 -#define NotSameDevice 0x11 -#define NoMoreFiles 0x12 -#define WriteProtected 0x13 -#define UnknownUnit 0x14 -#define DriveNotReady 0x15 -#define UnknownCommand 0x16 -#define CRCError 0x17 -#define BadRqLength 0x18 -#define SeekError 0x19 -#define UnknownMedia 0x1a -#define SectorNotFound 0x1b -#define OutOfPaper 0x1c -#define WriteFault 0x1d -#define ReadFault 0x1e -#define GeneralFailure 0x1f -#define ShareViolation 0x20 -#define LockViolation 0x21 -#define DiskFull 0x27 -#define NoNetwork 0x49 -#define FileExists 0x50 -#define CanNotMakeDir 0x52 +extern WORD DOS_ExtendedError; +extern BYTE DOS_ErrorClass, DOS_ErrorAction, DOS_ErrorLocus; + +#define DOS_ERROR(err,class,action,locus) \ + ( DOS_ErrorClass = (class), DOS_ErrorAction = (action), \ + DOS_ErrorLocus = (locus), DOS_ExtendedError = (err) ) + +/* Error codes */ + +#define ER_NoError 0x00 +#define ER_InvalidFunction 0x01 +#define ER_FileNotFound 0x02 +#define ER_PathNotFound 0x03 +#define ER_TooManyOpenFiles 0x04 +#define ER_AccessDenied 0x05 +#define ER_InvalidHandle 0x06 +#define ER_MCBDestroyed 0x07 +#define ER_OutOfMemory 0x08 +#define ER_MCBInvalid 0x09 +#define ER_EnvironInvalid 0x0a +#define ER_FormatInvalid 0x0b +#define ER_AccessCodeInvalid 0x0c +#define ER_DataInvalid 0x0d +#define ER_InvalidDrive 0x0f +#define ER_CanNotRemoveCwd 0x10 +#define ER_NotSameDevice 0x11 +#define ER_NoMoreFiles 0x12 +#define ER_WriteProtected 0x13 +#define ER_UnknownUnit 0x14 +#define ER_DriveNotReady 0x15 +#define ER_UnknownCommand 0x16 +#define ER_CRCError 0x17 +#define ER_BadRqLength 0x18 +#define ER_SeekError 0x19 +#define ER_UnknownMedia 0x1a +#define ER_SectorNotFound 0x1b +#define ER_OutOfPaper 0x1c +#define ER_WriteFault 0x1d +#define ER_ReadFault 0x1e +#define ER_GeneralFailure 0x1f +#define ER_ShareViolation 0x20 +#define ER_LockViolation 0x21 +#define ER_DiskFull 0x27 +#define ER_NoNetwork 0x49 +#define ER_FileExists 0x50 +#define ER_CanNotMakeDir 0x52 /* Error classes */ -#define EC_Temporary 0x02 -#define EC_AccessDenied 0x03 -#define EC_AppError 0x04 -#define EC_SystemFailure 0x06 -#define EC_NotFound 0x08 -#define EC_MediaError 0x0b -#define EC_Exists 0x0c -#define EC_Unknown 0x0d +#define EC_OutOfResource 0x01 +#define EC_Temporary 0x02 +#define EC_AccessDenied 0x03 +#define EC_InternalError 0x04 +#define EC_HardwareFailure 0x05 +#define EC_SystemFailure 0x06 +#define EC_ProgramError 0x07 +#define EC_NotFound 0x08 +#define EC_MediaError 0x0b +#define EC_Exists 0x0c +#define EC_Unknown 0x0d /* Suggested actions */ -#define SA_Retry 0x01 -#define SA_Abort 0x04 -#define SA_Ignore 0x06 -#define SA_Ask4Retry 0x07 +#define SA_Retry 0x01 +#define SA_DelayedRetry 0x02 +#define SA_Abort 0x04 +#define SA_Ignore 0x06 +#define SA_Ask4Retry 0x07 /* Error locus */ -#define EL_Unknown 0x01 -#define EL_Disk 0x02 -#define EL_Network 0x03 -#define EL_Memory 0x05 +#define EL_Unknown 0x01 +#define EL_Disk 0x02 +#define EL_Network 0x03 +#define EL_Serial 0x04 +#define EL_Memory 0x05 #endif /* __MSDOS_H */ diff --git a/include/pe_image.h b/include/pe_image.h index b83e6519bd2..220f5b23907 100644 --- a/include/pe_image.h +++ b/include/pe_image.h @@ -9,6 +9,10 @@ struct pe_data { struct PE_Import_Directory *pe_import; struct PE_Export_Directory *pe_export; struct PE_Resource_Directory *pe_resource; + struct PE_Reloc_Block *pe_reloc; + int base_addr; + int load_addr; + int vma_size; int resource_offset; /* offset to resource typedirectory in file */ }; @@ -18,7 +22,6 @@ struct w_files char * name; /* Name, as it appears in the windows binaries */ char * filename; /* Actual name of the unix file that satisfies this */ int type; /* DLL or EXE */ - int fd; HINSTANCE hinstance; HMODULE hModule; int initialised; @@ -31,8 +34,7 @@ struct w_files extern int PE_unloadImage(struct w_files *wpnt); extern int PE_StartProgram(struct w_files *wpnt); -extern void PE_InitDLL(struct w_files *wpnt); -extern HINSTANCE PE_LoadImage(struct w_files *wpnt); +extern void PE_InitDLL(HMODULE hModule); extern void my_wcstombs(char * result, u_short * source, int len); extern struct w_files *wine_files; diff --git a/include/peexe.h b/include/peexe.h index 43aa48a9e57..ff85a084609 100644 --- a/include/peexe.h +++ b/include/peexe.h @@ -167,7 +167,7 @@ struct PE_Export_Directory u_long * AddressOfFunctions; u_long * AddressOfNames; u_short * Address_Of_Name_Ordinals; - u_char ModuleName[1]; +/* u_char ModuleName[1]; */ }; /* @@ -213,4 +213,18 @@ struct PE_Resource_Leaf_Entry #define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 #define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 +struct PE_Reloc_Block +{ + u_long PageRVA; + u_long BlockSize; + short Relocations[1]; +}; + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 + #endif /* __WINE_PEEXE_H */ diff --git a/include/registers.h b/include/registers.h index 2114b54859b..93a9567ce53 100644 --- a/include/registers.h +++ b/include/registers.h @@ -106,10 +106,18 @@ #define EIP_reg(context) ((context)->uc_mcontext.gregs[EIP]) +#ifdef R_ESP #define ESP_reg(context) ((context)->uc_mcontext.gregs[R_ESP]) +#else +#define ESP_reg(context) ((context)->uc_mcontext.gregs[ESP]) +#endif #define IP_reg(context) (*(WORD*)(&(context)->uc_mcontext.gregs[EIP])) +#ifdef R_ESP #define SP_reg(context) (*(WORD*)(&(context)->uc_mcontext.gregs[R_ESP])) +#else +#define SP_reg(context) (*(WORD*)(&(context)->uc_mcontext.gregs[ESP])) +#endif #define SET_CFLAG(context) (EFL_reg(context) |= 0x0001) #define RESET_CFLAG(context) (EFL_reg(context) &= 0xfffffffe) diff --git a/include/resource32.h b/include/resource32.h new file mode 100644 index 00000000000..6a2ac433327 --- /dev/null +++ b/include/resource32.h @@ -0,0 +1,47 @@ +/* + * Win32 functions, structures, and types related to resources + * + * Copyright 1995 Thomas Sandford + * + */ + +#ifndef __WINE_RESOURCE32_H +#define __WINE_RESOURCE32_H + +#include + +HANDLE32 FindResource32( HINSTANCE hModule, LPCTSTR name, LPCTSTR type ); +HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc ); +LPVOID LockResource32( HANDLE32 handle ); +BOOL FreeResource32( HANDLE32 handle ); +INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc ); +DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc ); +int LoadString32(HINSTANCE instance, DWORD resource_id, LPTSTR buffer, int buflen); + +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + DWORD Name; + DWORD OffsetToData; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + WORD Length; + WCHAR NameString[1]; +} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; + +#endif /* __WINE_RESOURCE32_H */ diff --git a/include/stackframe.h b/include/stackframe.h index cf4358bbdf4..a9d4020be5c 100644 --- a/include/stackframe.h +++ b/include/stackframe.h @@ -66,9 +66,12 @@ extern DWORD IF1632_Original32_esp; /* Make a segmented pointer from a pointer to a variable located */ /* on the 32-bit stack for the current task. */ +#if 0 #define MAKE_SEGPTR(ptr) \ ((SEGPTR)IF1632_Stack32_base + \ ((DWORD)(ptr) - (DWORD)PTR_SEG_TO_LIN(IF1632_Stack32_base))) +#endif +SEGPTR MAKE_SEGPTR(void *ptr); #else #define CURRENT_STACK16 error.error #define CURRENT_DS 0 diff --git a/include/task.h b/include/task.h index fd5604db0f3..d2a2b30ebff 100644 --- a/include/task.h +++ b/include/task.h @@ -21,20 +21,23 @@ extern void TASK_KillCurrentTask( int exitCode ); typedef struct { - WORD int20; /* int 20h instruction */ - WORD nextParagraph; /* Segment of next paragraph */ + WORD int20; /* 00 int 20h instruction */ + WORD nextParagraph; /* 02 Segment of next paragraph */ BYTE reserved1; - BYTE dispatcher[5]; /* Long call to DOS */ - SEGPTR savedint22; /* Saved int 22h handler */ - SEGPTR savedint23; /* Saved int 23h handler */ - SEGPTR savedint24; /* Saved int 24h handler */ - WORD parentPSP; /* Selector of parent PSP */ - BYTE fileHandles[20]; /* Open file handles */ - HANDLE environment; /* Selector of environment */ - WORD reserved2[23]; - BYTE fcb1[16]; /* First FCB */ - BYTE fcb2[20]; /* Second FCB */ - BYTE cmdLine[128]; /* Command-line (first byte is length) */ + BYTE dispatcher[5]; /* 05 Long call to DOS */ + SEGPTR savedint22 WINE_PACKED; /* 0a Saved int 22h handler */ + SEGPTR savedint23 WINE_PACKED; /* 0e Saved int 23h handler */ + SEGPTR savedint24 WINE_PACKED; /* 12 Saved int 24h handler */ + WORD parentPSP; /* 16 Selector of parent PSP */ + BYTE fileHandles[20]; /* 18 Open file handles */ + HANDLE environment; /* 2c Selector of environment */ + WORD reserved2[2]; + WORD nbFiles; /* 32 Number of file handles */ + SEGPTR fileHandlesPtr; /* 34 Pointer to file handle table */ + WORD reserved3[18]; + BYTE fcb1[16]; /* 5c First FCB */ + BYTE fcb2[20]; /* 6c Second FCB */ + BYTE cmdLine[128]; /* 80 Command-line (first byte is len) */ } PDB; @@ -66,7 +69,7 @@ typedef struct DWORD esp; /* 32-bit stack pointer */ WORD ctrlword8087; /* 80x87 control word */ WORD flags; /* Task flags */ - WORD error_flags; /* Error handling flags */ + UINT error_mode; /* Error mode (see SetErrorMode) */ WORD version; /* Expected Windows version */ HANDLE hInstance; /* Instance handle for this task */ HMODULE hModule; /* Module handle */ diff --git a/include/toolhelp.h b/include/toolhelp.h index 5ffb1b4b784..43d0e7f3128 100644 --- a/include/toolhelp.h +++ b/include/toolhelp.h @@ -232,6 +232,15 @@ typedef struct BOOL MemManInfo(LPMEMMANINFO lpEnhMode); BOOL SystemHeapInfo( SYSHEAPINFO *pHeapInfo ); +/* timer info */ + +typedef struct tagTIMERINFO { + DWORD dwSize; + DWORD dwmsSinceStart; + DWORD dwmsThisVM; +} TIMERINFO; + +BOOL TimerInfo( TIMERINFO *pTimerInfo ); /* Window classes */ diff --git a/include/windows.h b/include/windows.h index 3934834a878..b7f82984e71 100644 --- a/include/windows.h +++ b/include/windows.h @@ -765,6 +765,9 @@ typedef struct tagLOGPEN #define WINDING 2 /* Background modes */ +#ifdef TRANSPARENT /*Apparently some broken svr4 includes define TRANSPARENT*/ +#undef TRANSPARENT +#endif #define TRANSPARENT 1 #define OPAQUE 2 @@ -1034,37 +1037,42 @@ typedef KANJISTRUCT *LPKANJISTRUCT; typedef KANJISTRUCT *NPKANJISTRUCT; typedef KANJISTRUCT *PKANJISTRUCT; -typedef struct { - BYTE cBytes, fFixedDisk; - WORD nErrCode; - BYTE reserved[4], szPathName[128]; +typedef struct +{ + BYTE cBytes; + BYTE fFixedDisk; + WORD nErrCode; + BYTE reserved[4]; + BYTE szPathName[128]; } OFSTRUCT; -typedef OFSTRUCT *POFSTRUCT; -typedef OFSTRUCT *NPOFSTRUCT; typedef OFSTRUCT *LPOFSTRUCT; -#define OF_READ 0x0000 -#define OF_WRITE 0x0001 -#define OF_READWRITE 0x0002 -#define OF_CANCEL 0x0800 -#define OF_CREATE 0x1000 -#define OF_DELETE 0x0200 -#define OF_EXIST 0x4000 -#define OF_PARSE 0x0100 -#define OF_PROMPT 0x2000 -#define OF_REOPEN 0x8000 -#define OF_SHARE_COMPAT 0x0000 -#define OF_SHARE_DENY_NONE 0x0040 -#define OF_SHARE_DENY_READ 0x0030 -#define OF_SHARE_DENY_WRITE 0x0020 -#define OF_SHARE_EXCLUSIVE 0x0010 -#define OF_VERIFY 0x0400 +#define OF_READ 0x0000 +#define OF_WRITE 0x0001 +#define OF_READWRITE 0x0002 +#define OF_SHARE_COMPAT 0x0000 +#define OF_SHARE_EXCLUSIVE 0x0010 +#define OF_SHARE_DENY_WRITE 0x0020 +#define OF_SHARE_DENY_READ 0x0030 +#define OF_SHARE_DENY_NONE 0x0040 +#define OF_PARSE 0x0100 +#define OF_DELETE 0x0200 +#define OF_VERIFY 0x0400 /* Used with OF_REOPEN */ +#define OF_SEARCH 0x0400 /* Used without OF_REOPEN */ +#define OF_CANCEL 0x0800 +#define OF_CREATE 0x1000 +#define OF_PROMPT 0x2000 +#define OF_EXIST 0x4000 +#define OF_REOPEN 0x8000 -#define DRIVE_CANNOTDETERMINE 0 -#define DRIVE_DOESNOTEXIST 1 -#define DRIVE_REMOVABLE 2 -#define DRIVE_FIXED 3 -#define DRIVE_REMOTE 4 +/* GetTempFileName() Flags */ +#define TF_FORCEDRIVE 0x80 + +#define DRIVE_CANNOTDETERMINE 0 +#define DRIVE_DOESNOTEXIST 1 +#define DRIVE_REMOVABLE 2 +#define DRIVE_FIXED 3 +#define DRIVE_REMOTE 4 #define HFILE_ERROR -1 @@ -1687,6 +1695,8 @@ typedef struct tagDRAGINFO { #define SW_SHOWMINNOACTIVE 7 #define SW_SHOWNA 8 #define SW_RESTORE 9 +#define SW_SHOWDEFAULT 10 +#define SW_MAX 10 /* WM_SIZE message wParam values */ #define SIZE_RESTORED 0 @@ -2648,8 +2658,8 @@ int DialogBoxParam(HANDLE,SEGPTR,HWND,WNDPROC,LONG); HANDLE DirectResAlloc(HANDLE,WORD,WORD); void DirectedYield(HTASK); LONG DispatchMessage(LPMSG); -int DlgDirList(HWND,LPSTR,int,int,WORD); -int DlgDirListComboBox(HWND,SEGPTR,int,int,WORD); +INT DlgDirList(HWND,SEGPTR,INT,INT,WORD); +INT DlgDirListComboBox(HWND,SEGPTR,INT,INT,WORD); BOOL DlgDirSelect(HWND,LPSTR,int); BOOL DlgDirSelectComboBox(HWND,LPSTR,int); BOOL DragDetect(HWND,POINT); @@ -2808,11 +2818,11 @@ HWND GetParent(HWND); DWORD GetPixel(HDC,short,short); WORD GetPolyFillMode(HDC); int GetPriorityClipboardFormat(WORD*,short); -WORD GetPrivateProfileInt(LPSTR,LPSTR,short,LPSTR); -short GetPrivateProfileString(LPSTR,LPSTR,LPSTR,LPSTR,short,LPSTR); +WORD GetPrivateProfileInt(LPCSTR,LPCSTR,short,LPCSTR); +short GetPrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,short,LPCSTR); FARPROC GetProcAddress(HANDLE,SEGPTR); -WORD GetProfileInt(LPSTR,LPSTR,int); -int GetProfileString(LPSTR,LPSTR,LPSTR,LPSTR,int); +WORD GetProfileInt(LPCSTR,LPCSTR,int); +int GetProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,int); HANDLE GetProp(HWND,SEGPTR); WORD GetROP2(HDC); WORD GetRelAbs(HDC); @@ -2933,6 +2943,7 @@ BOOL IsDialogMessage(HWND,LPMSG); WORD IsDlgButtonChecked(HWND,WORD); BOOL IsIconic(HWND); BOOL IsRectEmpty(LPRECT); +HTASK IsTaskLocked(void); BOOL IsTwoByteCharPrefix(char); BOOL IsWindow(HWND); BOOL IsWindowEnabled(HWND); @@ -2996,7 +3007,7 @@ DWORD OffsetWindowOrg(HDC,short,short); BOOL OffsetWindowOrgEx(HDC,short,short,LPPOINT); BOOL OpenClipboard(HWND); int OpenComm(LPSTR,UINT,UINT); -INT OpenFile(LPCSTR,LPOFSTRUCT,UINT); +HFILE OpenFile(LPCSTR,OFSTRUCT*,UINT); BOOL OpenIcon(HWND); int OpenSound(void); void OutputDebugString(LPSTR); @@ -3088,12 +3099,12 @@ void SetDCState(HDC,HDC); int SetDIBits(HDC,HANDLE,WORD,WORD,LPSTR,LPBITMAPINFO,WORD); int SetDIBitsToDevice(HDC,short,short,WORD,WORD,WORD,WORD,WORD,WORD,LPSTR,LPBITMAPINFO,WORD); BOOL SetDeskPattern(void); -BOOL SetDeskWallPaper(LPSTR); +BOOL SetDeskWallPaper(LPCSTR); void SetDlgItemInt(HWND,WORD,WORD,BOOL); void SetDlgItemText(HWND,WORD,SEGPTR); void SetDoubleClickTime(WORD); int SetEnvironment(LPSTR,LPSTR,WORD); -BOOL SetErrorMode(WORD); +UINT SetErrorMode(UINT); HWND SetFocus(HWND); WORD SetHandleCount(WORD); void SetInternalWindowPos(HWND,WORD,LPRECT,LPPOINT); @@ -3206,19 +3217,20 @@ int WriteComm(int,LPSTR,int); BOOL WritePrivateProfileString(LPSTR,LPSTR,LPSTR,LPSTR); BOOL WriteProfileString(LPSTR,LPSTR,LPSTR); void Yield(void); -LONG _hread(INT,LPSTR,LONG); -LONG _hwrite(INT,LPCSTR,LONG); -INT _lclose(INT); -INT _lcreat(LPSTR,INT); -LONG _llseek(INT,LONG,INT); -INT _lopen(LPSTR,INT); -INT _lread(INT,LPSTR,WORD); -INT _lwrite(INT,LPCSTR,WORD); +LONG _hread(HFILE,LPSTR,LONG); +LONG _hwrite(HFILE,LPCSTR,LONG); +HFILE _lclose(HFILE); +HFILE _lcreat(LPCSTR,INT); +LONG _llseek(HFILE,LONG,INT); +HFILE _lopen(LPCSTR,INT); +INT _lread(HFILE,LPSTR,WORD); +INT _lwrite(HFILE,LPCSTR,WORD); SEGPTR lstrcat(SEGPTR,SEGPTR); INT lstrcmp(LPCSTR,LPCSTR); INT lstrcmpi(LPCSTR,LPCSTR); +INT lstrncmpi(LPCSTR,LPCSTR,int); SEGPTR lstrcpy(SEGPTR,SEGPTR); -char * lstrcpyn(char *,char *,int); +char * lstrcpyn(char *,const char *,int); INT lstrlen(LPCSTR); int wvsprintf(LPSTR,LPSTR,LPSTR); diff --git a/include/wine.h b/include/wine.h index 29b6c44101b..8feab5476c1 100644 --- a/include/wine.h +++ b/include/wine.h @@ -1,11 +1,9 @@ -#ifndef WINE_H -#define WINE_H +#ifndef __WINE_WINE_H +#define __WINE_WINE_H extern char *WineIniFileName(void); -extern char *WinIniFileName(void); #define WINE_INI WineIniFileName() -#define WIN_INI WinIniFileName() #ifdef i386 extern int runtime_cpu (void); @@ -13,6 +11,7 @@ extern int runtime_cpu (void); static inline int runtime_cpu(void) { return 3; } #endif +#ifndef WINELIB #if defined ( linux) struct sigcontext_struct @@ -66,4 +65,6 @@ struct sigcontext_struct #define WINE_CODE_SELECTOR 0x1f #endif -#endif /* WINE_H */ +#endif /* WINELIB */ + +#endif /* __WINE_WINE_H */ diff --git a/include/winsock.h b/include/winsock.h index 6223573e55d..56a8fadfafd 100644 --- a/include/winsock.h +++ b/include/winsock.h @@ -7,6 +7,7 @@ #ifndef _WINSOCKAPI_ #define _WINSOCKAPI_ +#include #include #include #include @@ -26,12 +27,14 @@ extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *); /* * Internet address (old style... should be updated) */ +#ifdef WS_USE_OLD_STYLE #define s_addr S_un.S_addr /* can be used for most tcp & ip code */ #define s_host S_un.S_un_b.s_b2 /* host on imp */ #define s_net S_un.S_un_b.s_b1 /* network */ #define s_imp S_un.S_un_w.s_w2 /* imp */ #define s_impno S_un.S_un_b.s_b4 /* imp # */ #define s_lh S_un.S_un_b.s_b3 /* logical host */ +#endif #define WSADESCRIPTION_LEN 256 #define WSASYS_STATUS_LEN 128 @@ -62,23 +65,6 @@ typedef WSADATA FAR *LPWSADATA; #define SO_DONTLINGER (u_int)(~SO_LINGER) #endif -#ifndef _SYS_SOCKET_H_ -#ifndef _sys_socket_h -#ifndef _NET_TRANSPORT_SOCKET_H -#ifndef _NET_SOCKET_H -/* - * Structure used by kernel to pass protocol - * information in raw sockets. - */ -struct sockproto { - u_short sp_family; /* address family */ - u_short sp_protocol; /* protocol */ -}; -#endif -#endif -#endif -#endif - /* * Maximum queue length specifiable by listen. */ diff --git a/include/wintypes.h b/include/wintypes.h index 30ecb94bc7b..f0cc840eda0 100644 --- a/include/wintypes.h +++ b/include/wintypes.h @@ -48,6 +48,7 @@ typedef DWORD SEGPTR; #endif typedef LONG LPARAM; typedef LONG LRESULT; +typedef INT HFILE; typedef DWORD HHOOK; typedef char *LPSTR; typedef const char *LPCSTR; @@ -90,6 +91,8 @@ DECLARE_HANDLE(HTASK); DECLARE_HANDLE(HWND); DECLARE_HANDLE(LOCALHANDLE); +typedef HGLOBAL GLOBALHANDLE; + #ifdef WINELIB typedef long (*FARPROC)(); typedef LRESULT (*WNDPROC)(HWND,UINT,WPARAM,LPARAM); diff --git a/include/xmalloc.h b/include/xmalloc.h index e8b183df6cd..396fde0527b 100644 --- a/include/xmalloc.h +++ b/include/xmalloc.h @@ -1,3 +1,6 @@ +#ifndef __WINE_XMALLOC_H +#define __WINE_XMALLOC_H + #ifdef HAVE_STDLIB_H #include #else @@ -6,3 +9,6 @@ void *xmalloc (size_t); void *xrealloc (void *, size_t); +char *xstrdup( const char * ); + +#endif /* __WINE_XMALLOC_H */ diff --git a/ipc/dde_atom.c b/ipc/dde_atom.c index 5ca9b4255d4..6d249084824 100644 --- a/ipc/dde_atom.c +++ b/ipc/dde_atom.c @@ -66,7 +66,7 @@ static int FindHash(LPCSTR str) /* ignore str case */ deleted=hash1; break; default : /* non empty atom entry */ - if ( strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0) + if (lstrcmpi( OFS2AtomStr(atom_ofs) , str) == 0) return hash1; /* found string in atom table */ } hash2%= DDE_ATOMS-1 ; /* hash2=0..(DDE_ATOMS-2) */ @@ -92,7 +92,7 @@ static int FindHash(LPCSTR str) /* ignore str case */ deleted= i; break; default : /* nonempty atom entry */ - if ( strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0) + if (lstrcmpi( OFS2AtomStr(atom_ofs) , str) == 0) return i; /* found string in atom table */ } } diff --git a/library/atom.c b/library/atom.c index 48fbfbe3d0d..a87f938f0a8 100644 --- a/library/atom.c +++ b/library/atom.c @@ -80,7 +80,7 @@ static ATOM ATOM_AddAtom( ATOMtoHANDLEtable** tableptr, SEGPTR name ) FirstUnusedIndex=Index; } else if ((table->a2h[i].length == len) && - (!strncasecmp( table->a2h[i].str, str, len ))) + (!lstrncmpi( table->a2h[i].str, str, len ))) { table->a2h[i].refCount++; return Index; @@ -176,7 +176,7 @@ static ATOM ATOM_FindAtom( ATOMtoHANDLEtable** tableptr, SEGPTR name ) { if ((table->a2h[i].refCount != 0) && (table->a2h[i].length == len) && - (!strncasecmp( table->a2h[i].str, str, len ))) + (!lstrncmpi( table->a2h[i].str, str, len ))) return Index; } table=table->next; diff --git a/library/libres.c b/library/libres.c index 5f4c5b52c5b..0d1511ec79f 100644 --- a/library/libres.c +++ b/library/libres.c @@ -101,7 +101,6 @@ LPVOID LIBRES_LockResource( HGLOBAL handle ) */ BOOL LIBRES_FreeResource( HGLOBAL handle ) { - WINELIB_UNIMP("LIBRES_FreeResource()"); return 0; /* Obsolete in Win32 */ } diff --git a/library/miscstubs.c b/library/miscstubs.c index 8f62d4ca15c..c1cb479012f 100644 --- a/library/miscstubs.c +++ b/library/miscstubs.c @@ -45,7 +45,7 @@ WORD CallTo16_word_ ( FARPROC func, WORD arg ) { return func(arg); } void GlobalFreeAll(HANDLE owner) { - fprintf(stderr,"JBP: GlobalFreeAll() ignored.\n"); + WINELIB_UNIMP("GlobalFreeAll()"); } SEGPTR WIN16_GlobalLock(HGLOBAL h) @@ -65,7 +65,7 @@ WORD LOCAL_Size( WORD ds, HLOCAL handle ) void FarSetOwner(HANDLE a, WORD b) { - fprintf(stderr,"JBP: FarSetOwner() ignored.\n"); + WINELIB_UNIMP("FarSetOwner()"); } #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */ @@ -114,13 +114,11 @@ HGLOBAL GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size, BOOL is32Bit, BOOL isReadOnly, SHMDATA *shmdata) { -/* fprintf(stderr,"JBP: GLOBAL_CreateBlock() faked.\n");*/ return (HGLOBAL)ptr; } BOOL GLOBAL_FreeBlock( HGLOBAL handle ) { -/* fprintf(stderr,"JBP: GLOBAL_FreeBlock() ignored.\n");*/ return 1; } @@ -132,10 +130,10 @@ HGLOBAL GlobalHandle(LPCVOID a) void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint) { -/* fprintf(stderr,"JBP: RELAY32_GetEntryPoint() ignored.\n");*/ return NULL; } +extern LRESULT ACTIVATEAPP_callback(HWND,UINT,WPARAM,LPARAM); extern LRESULT AboutDlgProc(HWND,UINT,WPARAM,LPARAM); extern LRESULT ButtonWndProc(HWND,UINT,WPARAM,LPARAM); extern LRESULT CARET_Callback(HWND,UINT,WPARAM,LPARAM); @@ -172,6 +170,7 @@ LRESULT ErrorProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) WNDPROC GetWndProcEntry16( char *name ) { #define MAP_STR_TO_PROC(str,proc) if(!strcmp(name,str))return proc + MAP_STR_TO_PROC("ActivateAppProc",ACTIVATEAPP_callback); MAP_STR_TO_PROC("AboutDlgProc",AboutDlgProc); MAP_STR_TO_PROC("ButtonWndProc",ButtonWndProc); MAP_STR_TO_PROC("CARET_Callback",CARET_Callback); @@ -194,5 +193,6 @@ WNDPROC GetWndProcEntry16( char *name ) MAP_STR_TO_PROC("StaticWndProc",StaticWndProc); MAP_STR_TO_PROC("SystemMessageBoxProc",SystemMessageBoxProc); MAP_STR_TO_PROC("TASK_Reschedule",TASK_Reschedule); + fprintf(stderr,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name); return ErrorProc; } diff --git a/libtest/README.rolex b/libtest/README.rolex deleted file mode 100644 index a481683285c..00000000000 --- a/libtest/README.rolex +++ /dev/null @@ -1,8 +0,0 @@ -Windows clock application for WINE (by Jim Peterson) - -This is a translation of a Turbo Pascal OWL application I made once, -so it's a little flaky (tons of globals, functions that could have -been in-lined, etc.). The file rolex.exe is a Win32 application -compiled using this source code and Borland C++ 4.0. - -To try it out, type 'make rolex' or 'wine ./rolex.exe' (which fails). diff --git a/libtest/rolex.c b/libtest/rolex.c index fc71f796952..2f5212c8cbb 100644 --- a/libtest/rolex.c +++ b/libtest/rolex.c @@ -1,3 +1,16 @@ +/********************************************************************* + * * + * rolex.c: Windows clock application for WINE (by Jim Peterson) * + * * + * This is a translation of a Turbo Pascal OWL application I made * + * once, so it's a little flaky (tons of globals, functions that * + * could have been in-lined, etc.). The source code should easily * + * compile with a standard Win32 C compiler. * + * * + * To try it out, type 'make rolex'. * + * * + *********************************************************************/ + #include #include #include "windows.h" diff --git a/loader/main.c b/loader/main.c index de7df1efb32..8ee5a4e145a 100644 --- a/loader/main.c +++ b/loader/main.c @@ -20,12 +20,13 @@ static char Copyright[] = "Copyright Robert J. Amstadt, 1993"; #include "kernel32.h" #include "atom.h" #include "dialog.h" +#include "directory.h" +#include "drive.h" #include "message.h" #include "syscolor.h" #include "sysmetrics.h" #include "gdi.h" #include "debugger.h" -#include "dos_fs.h" #include "dlls.h" #include "miscemu.h" #include "neexe.h" @@ -63,8 +64,11 @@ int MAIN_Init(void) /* Create built-in modules */ if (!MODULE_Init()) return 0; - /* Initialize the DOS file system */ - DOS_InitFS(); + /* Initialise DOS drives */ + if (!DRIVE_Init()) return 0; + + /* Initialise DOS directories */ + if (!DIR_Init()) return 0; /* Initialize tasks */ if (!TASK_Init()) return 0; diff --git a/loader/module.c b/loader/module.c index d46529dee6f..5c9557a0aa2 100644 --- a/loader/module.c +++ b/loader/module.c @@ -13,6 +13,7 @@ #include "windows.h" #include "dlls.h" #include "dos_fs.h" +#include "file.h" #include "global.h" #include "ldt.h" #include "module.h" @@ -56,7 +57,7 @@ static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force ) if ((p = strrchr( dllname, '.' ))) *p = '\0'; for (i = 0, table = dll_builtin_table; i < N_BUILTINS; i++, table++) - if (!strcasecmp( table->name, dllname )) break; + if (!lstrcmpi( table->name, dllname )) break; if (i >= N_BUILTINS) return 0; if (!table->used && !force) return 0; @@ -110,9 +111,6 @@ BOOL MODULE_Init(void) !MODULE_LoadBuiltin( "GDI", TRUE ) || !MODULE_LoadBuiltin( "USER", TRUE ) || !MODULE_LoadBuiltin( "WINPROCS", TRUE )) return FALSE; - -#else - fprintf(stderr, "JBP: MODULE_Init() ignored.\n"); #endif /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */ @@ -260,6 +258,7 @@ int MODULE_OpenFile( HMODULE hModule ) { NE_MODULE *pModule; char *name; + const char *unixName; static int cachedfd = -1; @@ -271,19 +270,21 @@ int MODULE_OpenFile( HMODULE hModule ) close( cachedfd ); hCachedModule = hModule; name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename; - if ((cachedfd = open( DOS_GetUnixFileName( name ), O_RDONLY )) == -1) + if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) || + (cachedfd = open( unixName, O_RDONLY )) == -1) fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module "NPFMT"\n", name, hModule ); dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n", name, cachedfd ); return cachedfd; } + + /*********************************************************************** * MODULE_Ne2MemFlags + * + * This function translates NE segment flags to GlobalAlloc flags */ - -/* This function translates NE segment flags to GlobalAlloc flags */ - static WORD MODULE_Ne2MemFlags(WORD flags) { WORD memflags = 0; @@ -812,6 +813,17 @@ LPSTR MODULE_GetModuleName( HMODULE hModule ) } +/********************************************************************** + * MODULE_RegisterModule + */ +void MODULE_RegisterModule( HMODULE hModule ) +{ + NE_MODULE *pModule; + pModule = (NE_MODULE *)GlobalLock( hModule ); + pModule->next = hFirstModule; + hFirstModule = hModule; +} + /********************************************************************** * MODULE_FindModule * @@ -837,10 +849,10 @@ HMODULE MODULE_FindModule( LPCSTR path ) if (!(modulename = strrchr( modulepath, '\\' ))) modulename = modulepath; else modulename++; - if (!strcasecmp( modulename, filename )) return hModule; + if (!lstrcmpi( modulename, filename )) return hModule; name_table = (BYTE *)pModule + pModule->name_table; - if ((*name_table == len) && !strncasecmp(filename, name_table+1, len)) + if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len)) return hModule; hModule = pModule->next; } @@ -928,8 +940,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) /* Try to load the built-in first if not disabled */ if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule; - if (strchr( name, '/' )) name = DOS_GetDosFileName( name ); - if ((fd = OpenFile( name, &ofs, OF_READ )) == -1) + if ((fd = FILE_OpenFile( name, &ofs, OF_READ )) == -1) { /* Now try the built-in even if disabled */ if ((hModule = MODULE_LoadBuiltin( name, TRUE ))) @@ -942,11 +953,11 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) /* Create the module structure */ - if ((hModule = MODULE_LoadExeHeader( fd, &ofs )) < 32) + hModule = MODULE_LoadExeHeader( fd, &ofs ); + if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock ); + close( fd ); + if (hModule < 32) { - if(hModule == 21) - return PE_LoadModule(fd,&ofs,paramBlock); - close( fd ); fprintf( stderr, "LoadModule: can't load '%s', error=%d\n", name, hModule ); return hModule; @@ -1214,7 +1225,7 @@ HANDLE LoadLibrary( LPCSTR libname ) if (handle == (HANDLE)2) /* file not found */ { char buffer[256]; - strcpy( buffer, libname ); + lstrcpyn( buffer, libname, 252 ); strcat( buffer, ".dll" ); handle = LoadModule( buffer, (LPVOID)-1 ); } diff --git a/loader/ne_image.c b/loader/ne_image.c index eff083efbff..80eea87e9ab 100644 --- a/loader/ne_image.c +++ b/loader/ne_image.c @@ -508,6 +508,11 @@ void NE_InitializeDLLs( HMODULE hModule ) HMODULE *pDLL; pModule = (NE_MODULE *)GlobalLock( hModule ); + if (pModule->magic == PE_SIGNATURE) + { + PE_InitializeDLLs(hModule); + return; + } if (pModule->dlls_to_init) { HANDLE to_init = pModule->dlls_to_init; diff --git a/loader/ne_resource.c b/loader/ne_resource.c index caf1e0da997..5eee68293e0 100644 --- a/loader/ne_resource.c +++ b/loader/ne_resource.c @@ -67,8 +67,8 @@ static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId ) if (p[1] & 0x8000) { if (!HIWORD(typeId)) continue; - if (strcasecmp( (char *)PTR_SEG_TO_LIN(typeId), - (char *)(p + 3) )) continue; + if (lstrcmpi( (char *)PTR_SEG_TO_LIN(typeId), + (char *)(p + 3) )) continue; } else if (HIWORD(typeId) || ((typeId & ~0x8000)!= p[1])) continue; @@ -78,7 +78,7 @@ static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId ) if (p[2] & 0x8000) { if (!HIWORD(resId)) continue; - if (strcasecmp( (char *)PTR_SEG_TO_LIN(resId), + if (lstrcmpi( (char *)PTR_SEG_TO_LIN(resId), (char*)(p+3)+strlen((char*)(p+3))+1 )) continue; } @@ -119,7 +119,7 @@ static HRSRC NE_FindResourceFromType( NE_MODULE *pModule, { if (pNameInfo->id & 0x8000) continue; p = (BYTE *)pModule + pModule->res_table + pNameInfo->id; - if ((*p == len) && !strncasecmp( p+1, str, len )) + if ((*p == len) && !lstrncmpi( p+1, str, len )) return (HRSRC)((int)pNameInfo - (int)pModule); } } @@ -167,7 +167,7 @@ HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId ) if (!(pTypeInfo->type_id & 0x8000)) { BYTE *p = (BYTE*)pModule+pModule->res_table+pTypeInfo->type_id; - if ((*p == len) && !strncasecmp( p+1, str, len )) + if ((*p == len) && !lstrncmpi( p+1, str, len )) { dprintf_resource( stddeb, " Found type '%s'\n", str ); hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId); @@ -240,20 +240,21 @@ int NE_AccessResource( HMODULE hModule, HRSRC hRsrc ) { NE_MODULE *pModule; NE_NAMEINFO *pNameInfo=NULL; - WORD sizeShift; char *name; int fd; pModule = (NE_MODULE *)GlobalLock( hModule ); - if (!pModule || !pModule->res_table) return 0; + if (!pModule || !pModule->res_table) return -1; #ifndef WINELIB pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc); #endif name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename; - fd = open( DOS_GetUnixFileName(name), O_RDONLY ); - sizeShift = *(WORD *)((char *)pModule + pModule->res_table); - lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET ); + if ((fd = _lopen( name, OF_READ )) != -1) + { + WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table); + _llseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET ); + } return fd; } diff --git a/loader/pe_image.c b/loader/pe_image.c index 8a05457afa8..f7f3f72fdcc 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -33,8 +33,6 @@ #include "debug.h" #include "xmalloc.h" -#define MAP_ANONYMOUS 0x20 - struct w_files *wine_files = NULL; void my_wcstombs(char * result, u_short * source, int len) @@ -48,6 +46,7 @@ void my_wcstombs(char * result, u_short * source, int len) }; } +#if 0 char * xmmap(char * vaddr, unsigned int v_size, unsigned int r_size, int prot, int flags, int fd, unsigned int file_offset) { @@ -75,6 +74,7 @@ char * xmmap(char * vaddr, unsigned int v_size, unsigned int r_size, read(fd, vaddr, v_size); return vaddr; }; +#endif void dump_exports(struct PE_Export_Directory * pe_exports, unsigned int load_addr) { @@ -102,14 +102,76 @@ void dump_exports(struct PE_Export_Directory * pe_exports, unsigned int load_add } } -void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr) +DWORD PE_FindExportedFunction(struct w_files* wpnt, char* funcName) +{ + struct PE_Export_Directory * exports = wpnt->pe->pe_export; + unsigned load_addr = wpnt->pe->load_addr; + u_short * ordinal; + u_long * function; + u_char ** name, *ename; + int i; + if(!exports)return 0; + ordinal = (u_short *) (((char *) load_addr) + (int) exports->Address_Of_Name_Ordinals); + function = (u_long *) (((char *) load_addr) + (int) exports->AddressOfFunctions); + name = (u_char **) (((char *) load_addr) + (int) exports->AddressOfNames); + for(i=0; iNumber_Of_Functions; i++) + { + ename = (char *) (((char *) load_addr) + (int) *name); + if(strcmp(ename,funcName)==0) + return load_addr+*function; + function++; + ordinal++; + name++; + } + return 0; +} + +DWORD PE_GetProcAddress(HMODULE hModule, char* function) +{ + struct w_files *wpnt; + for(wpnt=wine_files;wpnt;wpnt=wpnt->next) + if(wpnt->hModule==hModule) break; + if(!wpnt)return 0; + return PE_FindExportedFunction(wpnt,function); +} + +void fixup_imports(struct w_files* wpnt) { struct PE_Import_Directory * pe_imp; int fixup_failed=0; + unsigned int load_addr = wpnt->pe->load_addr; + int i; + NE_MODULE *ne_mod; + HMODULE *mod_ptr; /* OK, now dump the import list */ dprintf_win32(stddeb, "\nDumping imports list\n"); - pe_imp = pe_imports; + + /* first, count the number of imported non-internal modules */ + pe_imp = wpnt->pe->pe_import; + for(i=0;pe_imp->ModuleName;pe_imp++) + i++; + + /* Now, allocate memory for dlls_to_init */ + ne_mod = GlobalLock(wpnt->hModule); + ne_mod->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,(i+1) * sizeof(HMODULE), + wpnt->hModule, FALSE, FALSE, FALSE ); + mod_ptr = GlobalLock(ne_mod->dlls_to_init); + /* load the modules and put their handles into the list */ + for(i=0,pe_imp = wpnt->pe->pe_import;pe_imp->ModuleName;pe_imp++) + { + char *name = (char*)load_addr+pe_imp->ModuleName; + if(RELAY32_GetBuiltinDLL(name)) + continue; + mod_ptr[i] = LoadModule(name,(LPVOID)-1); + if(mod_ptr[i]<=(HMODULE)32) + { + fprintf(stderr,"Module %s not found\n",name); + exit(0); + } + i++; + } + pe_imp = wpnt->pe->pe_import; while (pe_imp->ModuleName) { char * Module; @@ -126,6 +188,8 @@ void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr if (c) *c = 0; #endif + if(pe_imp->Import_List != 0) { /* original microsoft style */ + dprintf_win32(stddeb, "Microsoft style imports used\n"); import_list = (unsigned int *) (((unsigned int) load_addr) + pe_imp->Import_List); thunk_list = (unsigned int *) @@ -142,7 +206,12 @@ void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr } dprintf_win32(stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint); #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */ + /* Both calls should be unified into GetProcAddress */ *thunk_list=(unsigned int)RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint); + if(*thunk_list == 0) + *thunk_list = WIN32_GetProcAddress(MODULE_FindModule(Module), + pe_name->Name); + #else fprintf(stderr,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n"); #endif @@ -155,12 +224,35 @@ void fixup_imports(struct PE_Import_Directory *pe_imports,unsigned int load_addr import_list++; thunk_list++; } - pe_imp++; - }; - if(fixup_failed)exit(1); + } else { /* Borland style */ + dprintf_win32(stddeb, "Borland style imports used\n"); + thunk_list = (unsigned int *) + (((unsigned int) load_addr) + pe_imp->Thunk_List); + while(*thunk_list) { + pe_name = (struct pe_import_name *) ((int) load_addr + *thunk_list); + if((unsigned)pe_name & 0x80000000) { + fprintf(stderr,"Import by ordinal not supported\n"); + exit(0); + } + dprintf_win32(stddeb, "--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint); +#ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */ + *thunk_list=(unsigned int)RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint); +#else + fprintf(stderr,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n"); +#endif + if(!*thunk_list) { + fprintf(stderr,"No implementation for %s.%d\n",Module, pe_name->Hint); + fixup_failed=1; + } + thunk_list++; + } + } + pe_imp++; + } + if(fixup_failed)exit(1); } -static void dump_table(struct w_files *wpnt) +static void calc_vma_size(struct w_files *wpnt) { int i; @@ -179,48 +271,138 @@ static void dump_table(struct w_files *wpnt) wpnt->pe->pe_seg[i].NumberOfRelocations, wpnt->pe->pe_seg[i].NumberOfLinenumbers, wpnt->pe->pe_seg[i].Characteristics); + wpnt->pe->vma_size = max(wpnt->pe->vma_size, + wpnt->pe->pe_seg[i].Virtual_Address + + wpnt->pe->pe_seg[i].Size_Of_Raw_Data); } } +static void do_relocations(struct w_files *wpnt) +{ + int delta = wpnt->pe->load_addr - wpnt->pe->base_addr; + struct PE_Reloc_Block *r = wpnt->pe->pe_reloc; + int hdelta = (delta >> 16) & 0xFFFF; + int ldelta = delta & 0xFFFF; + /* int reloc_size = */ + if(delta == 0) + /* Nothing to do */ + return; + while(r->PageRVA) + { + char *page = (char*)wpnt->pe->load_addr + r->PageRVA; + int count = (r->BlockSize - 8)/2; + int i; + dprintf_fixup(stddeb, "%x relocations for page %lx\n", + count, r->PageRVA); + /* patching in reverse order */ + for(i=0;iRelocations[i] & 0xFFF; + int type = r->Relocations[i] >> 12; + dprintf_fixup(stddeb,"patching %x type %x\n", offset, type); + switch(type) + { + case IMAGE_REL_BASED_ABSOLUTE: break; + case IMAGE_REL_BASED_HIGH: + *(short*)(page+offset) += hdelta; + break; + case IMAGE_REL_BASED_LOW: + *(short*)(page+offset) += ldelta; + break; + case IMAGE_REL_BASED_HIGHLOW: +#if 1 + *(int*)(page+offset) += delta; +#else + { int h=*(unsigned short*)(page+offset); + int l=r->Relocations[++i]; + *(unsigned int*)(page + offset) = (h<<16) + l + delta; + } +#endif + break; + case IMAGE_REL_BASED_HIGHADJ: + fprintf(stderr, "Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n"); + break; + case IMAGE_REL_BASED_MIPS_JMPADDR: + fprintf(stderr, "Is this a MIPS machine ???\n"); + break; + default: + fprintf(stderr, "Unknown fixup type\n"); + break; + } + } + r = (struct PE_Reloc_Block*)((char*)r + r->BlockSize); + } +} + + + + + /********************************************************************** * PE_LoadImage * Load one PE format executable into memory */ -HINSTANCE PE_LoadImage(struct w_files *wpnt) +static HINSTANCE PE_LoadImage( int fd, struct w_files *wpnt ) { int i, result; - unsigned int load_addr; + unsigned int load_addr; wpnt->pe = xmalloc(sizeof(struct pe_data)); memset(wpnt->pe,0,sizeof(struct pe_data)); wpnt->pe->pe_header = xmalloc(sizeof(struct pe_header_s)); /* read PE header */ - lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET); - read(wpnt->fd, wpnt->pe->pe_header, sizeof(struct pe_header_s)); + lseek( fd, wpnt->mz_header->ne_offset, SEEK_SET); + read( fd, wpnt->pe->pe_header, sizeof(struct pe_header_s)); /* read sections */ wpnt->pe->pe_seg = xmalloc(sizeof(struct pe_segment_table) * wpnt->pe->pe_header->coff.NumberOfSections); - read(wpnt->fd, wpnt->pe->pe_seg, sizeof(struct pe_segment_table) * + read( fd, wpnt->pe->pe_seg, sizeof(struct pe_segment_table) * wpnt->pe->pe_header->coff.NumberOfSections); load_addr = wpnt->pe->pe_header->opt_coff.BaseOfImage; + wpnt->pe->base_addr=load_addr; + wpnt->pe->vma_size=0; dprintf_win32(stddeb, "Load addr is %x\n",load_addr); - dump_table(wpnt); + calc_vma_size(wpnt); + + /* We use malloc here, while a huge part of that address space does + not be supported by actual memory. It has to be contiguous, though. + I don't know if mmap("/dev/null"); would do any better. + What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile + sequence */ + load_addr = wpnt->pe->load_addr = malloc(wpnt->pe->vma_size); + dprintf_win32(stddeb, "Load addr is really %x, range %x\n", + wpnt->pe->load_addr, wpnt->pe->vma_size); + for(i=0; i < wpnt->pe->pe_header->coff.NumberOfSections; i++) { + /* load only non-BSS segments */ + if(wpnt->pe->pe_seg[i].Characteristics & + ~ IMAGE_SCN_TYPE_CNT_UNINITIALIZED_DATA) + if(lseek(fd,wpnt->pe->pe_seg[i].PointerToRawData,SEEK_SET) == -1 + || read(fd,load_addr + wpnt->pe->pe_seg[i].Virtual_Address, + wpnt->pe->pe_seg[i].Size_Of_Raw_Data) + != wpnt->pe->pe_seg[i].Size_Of_Raw_Data) + { + fprintf(stderr,"Failed to load section %x\n", i); + exit(0); + } + result = load_addr + wpnt->pe->pe_seg[i].Virtual_Address; +#if 0 if(!load_addr) { + result = (int)xmmap((char *)0, wpnt->pe->pe_seg[i].Virtual_Size, wpnt->pe->pe_seg[i].Size_Of_Raw_Data, 7, - MAP_PRIVATE, wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData); + MAP_PRIVATE, fd, wpnt->pe->pe_seg[i].PointerToRawData); load_addr = (unsigned int) result - wpnt->pe->pe_seg[i].Virtual_Address; } else { result = (int)xmmap((char *) load_addr + wpnt->pe->pe_seg[i].Virtual_Address, wpnt->pe->pe_seg[i].Virtual_Size, wpnt->pe->pe_seg[i].Size_Of_Raw_Data, 7, MAP_PRIVATE | MAP_FIXED, - wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData); + fd, wpnt->pe->pe_seg[i].PointerToRawData); } if(result==-1){ fprintf(stderr,"Could not load section %x to desired address %lx\n", @@ -228,6 +410,13 @@ HINSTANCE PE_LoadImage(struct w_files *wpnt) fprintf(stderr,"Need to implement relocations now\n"); exit(0); } +#endif + + if(strcmp(wpnt->pe->pe_seg[i].Name, ".bss") == 0) + memset((void *)result, 0, + wpnt->pe->pe_seg[i].Virtual_Size ? + wpnt->pe->pe_seg[i].Virtual_Size : + wpnt->pe->pe_seg[i].Size_Of_Raw_Data); if(strcmp(wpnt->pe->pe_seg[i].Name, ".idata") == 0) wpnt->pe->pe_import = (struct PE_Import_Directory *) result; @@ -242,10 +431,16 @@ HINSTANCE PE_LoadImage(struct w_files *wpnt) wpnt->pe->resource_offset = wpnt->pe->pe_seg[i].Virtual_Address - wpnt->pe->pe_seg[i].PointerToRawData; } + + if(strcmp(wpnt->pe->pe_seg[i].Name, ".reloc") == 0) + wpnt->pe->pe_reloc = (struct PE_Reloc_Block *) result; + } - if(wpnt->pe->pe_import) fixup_imports(wpnt->pe->pe_import,load_addr); + + if(wpnt->pe->pe_import) fixup_imports(wpnt); if(wpnt->pe->pe_export) dump_exports(wpnt->pe->pe_export,load_addr); + if(wpnt->pe->pe_reloc) do_relocations(wpnt); wpnt->hinstance = (HINSTANCE)0x8000; wpnt->load_addr = load_addr; @@ -271,7 +466,6 @@ HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params) wpnt=xmalloc(sizeof(struct w_files)); wpnt->ofs=*ofs; - wpnt->fd=fd; wpnt->type=0; wpnt->hinstance=0; wpnt->hModule=0; @@ -348,7 +542,9 @@ HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params) pModule->res_table=pModule->import_table=pModule->entry_table= (int)pStr-(int)pModule; - PE_LoadImage(wpnt); + MODULE_RegisterModule(hModule); + + PE_LoadImage( fd, wpnt ); pModule->heap_size=0x1000; pModule->stack_size=0xE000; @@ -358,34 +554,38 @@ HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params) wpnt->hinstance=hInstance; if (wpnt->pe->pe_export) { - wpnt->name = xmalloc(strlen(wpnt->pe->pe_export->ModuleName)+1); - strcpy(wpnt->name, wpnt->pe->pe_export->ModuleName); + pStr = ((unsigned char *)(wpnt->load_addr))+wpnt->pe->pe_export->Name; + wpnt->name = xstrdup(pStr); } else { - wpnt->name = xmalloc(strlen(ofs->szPathName)+1); - strcpy(wpnt->name, ofs->szPathName); + wpnt->name = xstrdup( ofs->szPathName ); } wpnt->next=wine_files; wine_files=wpnt; - if (!(wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL)) - TASK_CreateTask(hModule,hInstance,0, + /* FIXME: Is this really the correct place to initialise the DLL? */ + if ((wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL)) { + PE_InitDLL(wpnt); + } else { + TASK_CreateTask(hModule,hInstance,0, params->hEnvironment,(LPSTR)PTR_SEG_TO_LIN(params->cmdLine), *((WORD*)PTR_SEG_TO_LIN(params->showCmd)+1)); - + } return hInstance; } int USER_InitApp(HINSTANCE hInstance); +void PE_InitTEB(int hTEB); void PE_Win32CallToStart(struct sigcontext_struct context) { int fs; struct w_files *wpnt=wine_files; - fs=(int)GlobalAlloc(GHND,0x10000); dprintf_win32(stddeb,"Going to start Win32 program\n"); InitTask(context); USER_InitApp(wpnt->hModule); + fs=(int)GlobalAlloc(GHND,0x10000); + PE_InitTEB(fs); __asm__ __volatile__("movw %w0,%%fs"::"r" (fs)); ((void(*)())(wpnt->load_addr+wpnt->pe->pe_header->opt_coff.AddressOfEntryPoint))(); } @@ -397,11 +597,68 @@ int PE_UnloadImage(struct w_files *wpnt) return 1; } -void PE_InitDLL(struct w_files *wpnt) +void PE_InitDLL(HMODULE hModule) { + struct w_files *wpnt; + hModule = GetExePtr(hModule); + for(wpnt = wine_files;wpnt && wpnt->hModule != hModule; + wpnt = wpnt->next) /*nothing*/; + if(!wpnt || wpnt->initialised) + return; + /* FIXME: What are the correct values for parameters 2 and 3? */ + /* Is this a library? */ if (wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL) { + /* Should call DLLEntryPoint here */ printf("InitPEDLL() called!\n"); + wpnt->initialised = 1; + ((void(*)())(wpnt->load_addr+wpnt->pe->pe_header->opt_coff.AddressOfEntryPoint))(wpnt->hModule, 0, 0); } } + + +/* FIXME: This stuff is all on a "well it works" basis. An implementation +based on some kind of documentation would be greatly appreciated :-) */ + +typedef struct +{ + void *Except; + void *stack; + int dummy1[4]; + struct TEB *TEBDSAlias; + int dummy2[2]; + int taskid; +} TEB; + +void PE_InitTEB(int hTEB) +{ + TDB *pTask; + TEB *pTEB; + + pTask = (TDB *)(GlobalLock(GetCurrentTask() & 0xffff)); + pTEB = (TEB *)(PTR_SEG_OFF_TO_LIN(hTEB, 0)); + pTEB->stack = (void *)(GlobalLock(pTask->hStack32)); + pTEB->Except = (void *)(-1); + pTEB->TEBDSAlias = pTEB; + pTEB->taskid = getpid(); +} + +void PE_InitializeDLLs(HMODULE hModule) +{ + NE_MODULE *pModule; + HMODULE *pDLL; + pModule = (NE_MODULE *)GlobalLock( GetExePtr(hModule) ); + if (pModule->dlls_to_init) + { + HANDLE to_init = pModule->dlls_to_init; + pModule->dlls_to_init = 0; + for (pDLL = (HMODULE *)GlobalLock( to_init ); *pDLL; pDLL++) + { + PE_InitializeDLLs( *pDLL ); + PE_InitDLL( *pDLL ); + } + GlobalFree( to_init ); + } + PE_InitDLL( hModule ); +} #endif /* WINELIB */ diff --git a/loader/pe_resource.c b/loader/pe_resource.c index b9a356d1878..b0d62035857 100644 --- a/loader/pe_resource.c +++ b/loader/pe_resource.c @@ -72,7 +72,7 @@ find_resource(char *root, struct PE_Resource_Directory *resource, memset(res_name, 0, sizeof(res_name)); my_wcstombs(res_name, name->NameString, name->Length); dprintf_resource(stddeb, "\tPE_findresource: name %s\n", res_name); - if (strcasecmp(res_name, resource_name) == 0) + if (lstrcmpi(res_name, resource_name) == 0) return find_lang(root, (struct PE_Resource_Directory *) (root + (type_dir->OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY)), r); type_dir++; } @@ -107,7 +107,7 @@ find_type(struct PE_Resource_Directory *resource, LPSTR resource_name, my_wcstombs(res_name, name->NameString, name->Length); dprintf_resource(stddeb, "PE_findtype: type %s\n", res_name); - if (strcasecmp(res_name, type_name) == 0) + if (lstrcmpi(res_name, type_name) == 0) return find_resource(root, (struct PE_Resource_Directory *) (root + (type_dir->OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY)), resource_name, r); type_dir++; } diff --git a/loader/task.c b/loader/task.c index e7f2835d3b9..5e45faf3dec 100644 --- a/loader/task.c +++ b/loader/task.c @@ -10,7 +10,9 @@ #include "windows.h" #include "task.h" #include "callback.h" +#include "directory.h" #include "dos_fs.h" +#include "file.h" #include "debugger.h" #include "global.h" #include "instance.h" @@ -75,11 +77,10 @@ static HANDLE TASK_CreateDOSEnvironment(void) { static const char program_name[] = "KRNL386.EXE"; char **e, *p; - int initial_size, size; + int initial_size, size, i, winpathlen, windirlen, sysdirlen; HANDLE handle; extern char **environ; - extern char WindowsDirectory[], SystemDirectory[]; /* DOS environment format: * ASCIIZ string 1 @@ -95,20 +96,27 @@ static HANDLE TASK_CreateDOSEnvironment(void) /* First compute the size of the fixed part of the environment */ - initial_size = 5 + /* PATH= */ - strlen(WindowsPath) + 1 + /* path value */ - 7 + /* windir= */ - strlen(WindowsDirectory) + 1 + /* windir value */ - 1 + /* BYTE 0 at end */ - sizeof(WORD) + /* WORD 1 */ - strlen(SystemDirectory) + 1 + /* program directory */ - strlen(program_name) + 1; /* program name */ + for (i = winpathlen = 0; ; i++) + { + int len = DIR_GetDosPath( i, NULL, 0 ); + if (!len) break; + winpathlen += len + 1; + } + if (!winpathlen) winpathlen = 1; + windirlen = GetWindowsDirectory( NULL, 0 ) + 1; + sysdirlen = GetSystemDirectory( NULL, 0 ) + 1; + initial_size = 5 + winpathlen + /* PATH=xxxx */ + 7 + windirlen + /* windir=xxxx */ + 1 + /* BYTE 0 at end */ + sizeof(WORD) + /* WORD 1 */ + sysdirlen + /* program directory */ + strlen(program_name) + 1; /* program name */ /* Compute the total size of the Unix environment (except path) */ for (e = environ, size = initial_size; *e; e++) { - if (strncasecmp(*e, "path=", 5)) + if (lstrncmpi(*e, "path=", 5)) { int len = strlen(*e) + 1; if (size + len >= 32767) @@ -130,7 +138,7 @@ static HANDLE TASK_CreateDOSEnvironment(void) for (e = environ, size = initial_size; *e; e++) { - if (strncasecmp(*e, "path=", 5)) + if (lstrncmpi(*e, "path=", 5)) { int len = strlen(*e) + 1; if (size + len >= 32767) break; @@ -143,19 +151,25 @@ static HANDLE TASK_CreateDOSEnvironment(void) /* Now add the path and Windows directory */ strcpy( p, "PATH=" ); - strcat( p, WindowsPath ); - p += strlen(p) + 1; + for (i = 0, p += 5; ; i++) + { + if (!DIR_GetDosPath( i, p, winpathlen )) break; + p += strlen(p); + *p++ = ';'; + } + if (p[-1] == ';') p[-1] = '\0'; + else p++; strcpy( p, "windir=" ); - strcat( p, WindowsDirectory ); - p += strlen(p) + 1; + GetWindowsDirectory( p + 7, windirlen ); + p += 7 + windirlen; /* Now add the program name */ *p++ = '\0'; *(WORD *)p = 1; p += sizeof(WORD); - strcpy( p, SystemDirectory ); + GetSystemDirectory( p, sysdirlen ); strcat( p, "\\" ); strcat( p, program_name ); @@ -247,6 +261,7 @@ static void TASK_CreateThunks( HGLOBAL handle, WORD offset, WORD count ) * * Allocate a thunk for MakeProcInstance(). */ +#ifndef WINELIB32 static SEGPTR TASK_AllocThunk( HTASK hTask ) { TDB *pTask; @@ -275,6 +290,7 @@ static SEGPTR TASK_AllocThunk( HTASK hTask ) pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free); return MAKELONG( base, sel ); } +#endif /*********************************************************************** @@ -282,6 +298,7 @@ static SEGPTR TASK_AllocThunk( HTASK hTask ) * * Free a MakeProcInstance() thunk. */ +#ifndef WINELIB32 static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk ) { TDB *pTask; @@ -303,6 +320,7 @@ static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk ) pThunk->free = LOWORD(thunk) - base; return TRUE; } +#endif /*********************************************************************** @@ -335,10 +353,7 @@ static void TASK_CallToStart(void) cs_reg = pSegTable[pModule->cs - 1].selector; ip_reg = pModule->ip; ds_reg = pSegTable[pModule->dgroup - 1].selector; -#ifndef WINELIB -/* JBP: I doubt a CallTo16_regs_ is possible in libwine.a, and IF1632 is not - * allowed. - */ + IF1632_Saved16_ss = pTask->ss; IF1632_Saved16_sp = pTask->sp; dprintf_task( stddeb, "Starting main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n", @@ -349,11 +364,7 @@ static void TASK_CallToStart(void) pTask->hPDB /*es*/, 0 /*bp*/, 0 /*ax*/, pModule->stack_size /*bx*/, pModule->heap_size /*cx*/, 0 /*dx*/, 0 /*si*/, ds_reg /*di*/ ); -#else - fprintf(stderr, "JBP: Ignoring main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n", - cs_reg, ip_reg, ds_reg, - pTask->ss, pTask->sp); -#endif + /* This should never return */ fprintf( stderr, "TASK_CallToStart: Main program returned!\n" ); TASK_KillCurrentTask( 1 ); @@ -426,12 +437,13 @@ HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance, HANDLE hPrevInstance, pTask->hParent = hCurrentTask; #ifdef WINELIB pTask->curdrive = 'C' - 'A' + 0x80; + strcpy( pTask->curdir, "\\" ); #else pTask->curdrive = filename[0] - 'A' + 0x80; + strcpy( pTask->curdir, filename+2 ); #endif pTask->magic = TDB_MAGIC; pTask->nCmdShow = cmdShow; - strcpy( pTask->curdir, filename+2 ); /* Create the thunks block */ @@ -442,30 +454,35 @@ HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance, HANDLE hPrevInstance, name = MODULE_GetModuleName( hModule ); strncpy( pTask->module_name, name, sizeof(pTask->module_name) ); + /* Allocate a selector for the PDB */ + + pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB), + hModule, FALSE, FALSE, FALSE, NULL ); + /* Fill the PDB */ pTask->pdb.int20 = 0x20cd; +#ifndef WINELIB pTask->pdb.dispatcher[0] = 0x9a; /* ljmp */ *(DWORD *)&pTask->pdb.dispatcher[1] = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"), 102 ); /* KERNEL.102 is DOS3Call() */ -#ifndef WINELIB pTask->pdb.savedint22 = INT_GetHandler( 0x22 ); pTask->pdb.savedint23 = INT_GetHandler( 0x23 ); pTask->pdb.savedint24 = INT_GetHandler( 0x24 ); + pTask->pdb.fileHandlesPtr = (SEGPTR)MAKELONG( 0x18, + GlobalHandleToSel(pTask->hPDB) ); +#else + pTask->pdb.fileHandlesPtr = pTask->pdb.fileHandles; #endif - pTask->pdb.environment = hEnvironment; - strncpy( pTask->pdb.cmdLine + 1, cmdLine, 126 ); - pTask->pdb.cmdLine[127] = '\0'; + memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) ); + pTask->pdb.environment = hEnvironment; + pTask->pdb.nbFiles = 20; + lstrcpyn( pTask->pdb.cmdLine + 1, cmdLine, 127 ); pTask->pdb.cmdLine[0] = strlen( pTask->pdb.cmdLine + 1 ); /* Get the compatibility flags */ pTask->compat_flags = GetProfileInt( name, "Compatibility", 0 ); - /* Allocate a selector for the PDB */ - - pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB), - hModule, FALSE, FALSE, FALSE, NULL ); - /* Allocate a code segment alias for the TDB */ pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask, @@ -561,6 +578,10 @@ static void TASK_DeleteTask( HTASK hTask ) if (!(pTask = (TDB *)GlobalLock( hTask ))) return; + /* Close all open files of this task */ + + FILE_CloseAllFiles( pTask->hPDB ); + /* Free the task module */ FreeModule( pTask->hModule ); @@ -718,7 +739,11 @@ void TASK_Reschedule(void) /*********************************************************************** * InitTask (KERNEL.91) */ +#ifdef WINELIB +void InitTask(void) +#else void InitTask( struct sigcontext_struct context ) +#endif { static int firstTask = 1; TDB *pTask; @@ -727,7 +752,9 @@ void InitTask( struct sigcontext_struct context ) INSTANCEDATA *pinstance; LONG stacklow, stackhi; +#ifndef WINELIB EAX_reg(&context) = 0; +#endif if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return; if (!(pModule = (NE_MODULE *)GlobalLock( pTask->hModule ))) return; @@ -782,7 +809,7 @@ void InitTask( struct sigcontext_struct context ) pinstance = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN(CURRENT_DS, 0); pinstance->stackbottom = stackhi; /* yup, that's right. Confused me too. */ pinstance->stacktop = stacklow; -#ifndef WINELIB /* FIXME: JBP: IF1632 not allowed in libwine.a */ +#ifndef WINELIB pinstance->stackmin = IF1632_Saved16_sp; #endif } @@ -857,7 +884,7 @@ HTASK LockCurrentTask( BOOL bLock ) /*********************************************************************** * IsTaskLocked (KERNEL.122) */ -WORD IsTaskLocked(void) +HTASK IsTaskLocked(void) { return hLockedTask; } @@ -905,6 +932,9 @@ void Yield(void) */ FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance ) { +#ifdef WINELIB32 + return func; /* func can be called directly in Win32 */ +#else BYTE *thunk; SEGPTR thunkaddr; @@ -916,13 +946,12 @@ FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance ) (SEGPTR)func, hInstance, (SEGPTR)thunkaddr ); *thunk++ = 0xb8; /* movw instance, %ax */ -#ifndef WINELIB *thunk++ = (BYTE)(hInstance & 0xff); *thunk++ = (BYTE)(hInstance >> 8); -#endif *thunk++ = 0xea; /* ljmp func */ *(DWORD *)thunk = (DWORD)func; return (FARPROC)thunkaddr; +#endif } @@ -931,8 +960,10 @@ FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance ) */ void FreeProcInstance( FARPROC func ) { +#ifndef WINELIB32 dprintf_task( stddeb, "FreeProcInstance("SPFMT")\n", (SEGPTR)func ); TASK_FreeThunk( hCurrentTask, (SEGPTR)func ); +#endif } @@ -953,8 +984,6 @@ HANDLE GetCodeHandle( FARPROC proc ) else handle = GlobalHandle( HIWORD(proc) ); - printf( "STUB: GetCodeHandle(%08lx) returning "NPFMT"\n", - (DWORD)proc, handle ); return handle; } @@ -1049,6 +1078,21 @@ int GetInstanceData( HANDLE instance, WORD buffer, int len ) } +/*********************************************************************** + * SetErrorMode (KERNEL.107) + */ +UINT SetErrorMode( UINT mode ) +{ + TDB *pTask; + UINT oldMode; + + if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return 0; + oldMode = pTask->error_mode; + pTask->error_mode = mode; + return oldMode; +} + + /*********************************************************************** * GetDOSEnvironment (KERNEL.131) */ @@ -1108,6 +1152,8 @@ HMODULE GetExePtr( HANDLE handle ) if (!(ptr = GlobalLock( handle ))) return 0; if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return handle; + /* Fake modules describing PE modules have a PE signature */ + if (((NE_MODULE *)ptr)->magic == PE_SIGNATURE) return handle; /* Check the owner for module handle */ @@ -1115,10 +1161,10 @@ HMODULE GetExePtr( HANDLE handle ) owner = FarGetOwner( handle ); #else owner = NULL; - fprintf(stderr,"JBP: FarGetOwner() ignored.\n"); #endif if (!(ptr = GlobalLock( owner ))) return 0; if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return owner; + if (((NE_MODULE *)ptr)->magic == PE_SIGNATURE) return owner; /* Search for this handle and its owner inside all tasks */ diff --git a/memory/atom.c b/memory/atom.c index 359158c2a8c..0e42c92a414 100644 --- a/memory/atom.c +++ b/memory/atom.c @@ -146,7 +146,7 @@ static ATOM ATOM_AddAtom( WORD selector, SEGPTR name ) { entryPtr = ATOM_MakePtr( selector, entry ); if ((entryPtr->length == len) && - (!strncasecmp( entryPtr->str, str, len ))) + (!lstrncmpi( entryPtr->str, str, len ))) { entryPtr->refCount++; return HANDLETOATOM( entry ); @@ -227,7 +227,7 @@ static ATOM ATOM_FindAtom( WORD selector, SEGPTR name ) { ATOMENTRY * entryPtr = ATOM_MakePtr( selector, entry ); if ((entryPtr->length == len) && - (!strncasecmp( entryPtr->str, str, len ))) + (!lstrncmpi( entryPtr->str, str, len ))) return HANDLETOATOM( entry ); entry = entryPtr->next; } diff --git a/memory/global.c b/memory/global.c index 6d540a37462..680e9fb1053 100644 --- a/memory/global.c +++ b/memory/global.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "windows.h" @@ -755,7 +756,48 @@ BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg ) */ BOOL MemManInfo( MEMMANINFO *pInfo ) { +#ifdef linux + /* FIXME: does not take into account the dwSize member + * could be corrupting memory therefore + */ + /* shamefully stolen from free */ + DWORD availmem = 0; + DWORD totalmem = 0; + FILE *meminfo; + char buf[80]; + int col[5]; + int n; + + if ((meminfo = fopen("/proc/meminfo", "r")) < 0) { + perror("wine: open"); + exit(1); + } + + fgets(buf, 80, meminfo); /* read first line */ + while ( fgets(buf, 80, meminfo) ) { + n = sscanf( buf, "%*s %d %d %d %d %d", &col[0], &col[1], &col[2], &col[3], &col[4]); + if ( n < 1 ) continue; /* escape the loop at the top */ + totalmem += col[0]; + availmem += col[2] + col[4]; + } + + fprintf(stderr,"MemManInfo called with dwSize = %ld\n",pInfo->dwSize); + pInfo->wPageSize = getpagesize(); + pInfo->dwLargestFreeBlock = availmem; + pInfo->dwTotalLinearSpace = totalmem / pInfo->wPageSize; + pInfo->dwMaxPagesAvailable = pInfo->dwLargestFreeBlock / pInfo->wPageSize; + pInfo->dwMaxPagesLockable = pInfo->dwMaxPagesLockable; + /* FIXME: the next three are not quite correct */ + pInfo->dwTotalUnlockedPages = pInfo->dwMaxPagesAvailable; + pInfo->dwFreePages = pInfo->dwMaxPagesAvailable; + pInfo->dwTotalPages = pInfo->dwMaxPagesAvailable; + /* FIXME: the three above are not quite correct */ + pInfo->dwFreeLinearSpace = pInfo->dwMaxPagesAvailable; + pInfo->dwSwapFilePages = 0L; return TRUE; +#else + return TRUE; +#endif } /*********************************************************************** diff --git a/memory/ldt.c b/memory/ldt.c index 9500f2bd51f..bc1c96facae 100644 --- a/memory/ldt.c +++ b/memory/ldt.c @@ -7,11 +7,7 @@ #include #include -#ifdef __svr4__ #include -#else -#include -#endif #include #include "ldt.h" #include "stddebug.h" diff --git a/memory/selector.c b/memory/selector.c index d6c2db187df..bbf2e441349 100644 --- a/memory/selector.c +++ b/memory/selector.c @@ -442,3 +442,37 @@ DWORD MemoryWrite( WORD sel, DWORD offset, void *buffer, DWORD count ) memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count ); return count; } + +#ifndef WINELIB +SEGPTR MAKE_SEGPTR(void * ptr) + +{ + SEGPTR result; + int entry; + + if (!ptr) + return ptr; + if (!((unsigned)ptr & 0xffff0000)) { + fprintf(stderr, "Invalid pointer %08x has been passed to MAKE_SEGPTR. This was\n", ptr); + fprintf(stderr, "probably caused by an unnecessary call to PTR_SEG_TO_LIN.\n"); + fprintf(stderr, "Forcing call to debugger\n"); + ptr = *(void **)0; + } + result = (SEGPTR) (IF1632_Stack32_base) + + ((DWORD)(ptr) - (DWORD) PTR_SEG_TO_LIN(IF1632_Stack32_base)); + if (PTR_SEG_TO_LIN(result) == ptr) + return result; + + for (entry = 0; entry < LDT_SIZE; entry++) { + if (ldt_copy[entry].base && + (ldt_copy[entry].limit < 0x10000) && + ((unsigned) ptr >= ldt_copy[entry].base) && + ((unsigned) ptr < (ldt_copy[entry].base + ldt_copy[entry].limit))) { + return ((ENTRY_TO_SELECTOR(entry) << 16) | + ((unsigned) ptr - ldt_copy[entry].base)); + } + } + entry = SELECTOR_AllocBlock((void *)((unsigned)ptr & 0xffff0000), 0x10000, SEGMENT_DATA, 0, 0); + return ((entry << 16) | ((unsigned) ptr & 0xffff)); +} +#endif diff --git a/misc/Makefile.in b/misc/Makefile.in index d6374a565d4..7d0a5467431 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -10,7 +10,6 @@ C_SRCS = \ driver.c \ exec.c \ escape.c \ - file.c \ keyboard.c \ lstr.c \ main.c \ @@ -20,6 +19,7 @@ C_SRCS = \ ole2nls.c \ olecli.c \ olesvr.c \ + port.c \ profile.c \ rect.c \ shell.c \ diff --git a/misc/comm.c b/misc/comm.c index 06501cc4c50..107ec99f32d 100644 --- a/misc/comm.c +++ b/misc/comm.c @@ -136,7 +136,7 @@ int BuildCommDCB(LPSTR device, DCB FAR *lpdcb) "BuildCommDCB: (%s), ptr %p\n", device, lpdcb); commerror = 0; - if (!strncasecmp(device,"COM",3)) { + if (!lstrncmpi(device,"COM",3)) { port = device[3] - '0'; @@ -227,7 +227,7 @@ int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue) "OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue); commerror = 0; - if (!strncasecmp(device,"COM",3)) { + if (!lstrncmpi(device,"COM",3)) { port = device[3] - '0'; if (port-- == 0) { @@ -256,7 +256,7 @@ int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue) } } else - if (!strncasecmp(device,"LPT",3)) { + if (!lstrncmpi(device,"LPT",3)) { port = device[3] - '0'; if (!ValidLPTPort(port)) { diff --git a/misc/commdlg.c b/misc/commdlg.c index d147dde9b3c..8991597f014 100644 --- a/misc/commdlg.c +++ b/misc/commdlg.c @@ -15,6 +15,7 @@ #include "selectors.h" #include "resource.h" #include "dos_fs.h" +#include "drive.h" #include "stackframe.h" static DWORD CommDlgLastError = 0; @@ -164,9 +165,9 @@ static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath) strncpy(str,newPath,511); str[511]=0; SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 511, (LPARAM)MAKE_SEGPTR(str2)); strncat(str,str2,511-strlen(str)); str[511]=0; - if (!DlgDirList(hWnd, str, lst1, 0, 0x0000)) return FALSE; - DlgDirList(hWnd, "*.*", lst2, stc1, 0x8010); - + if (!DlgDirList(hWnd, MAKE_SEGPTR(str), lst1, 0, 0x0000)) return FALSE; + strcpy( str, "*.*" ); + DlgDirList(hWnd, MAKE_SEGPTR(str), lst2, stc1, 0x8010); return TRUE; } @@ -360,7 +361,7 @@ static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam) if (!FILEDLG_ScanDir(hWnd, tmpstr)) fprintf(stderr, "FileDlg: couldn't read initial directory %s!\n", tmpstr); /* select current drive in combo 2 */ - n = DOS_GetDefaultDrive(); + n = DRIVE_GetCurrentDrive(); SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, n, 0); if (!(lpofn->Flags & OFN_SHOWHELP)) ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE); @@ -378,13 +379,23 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) LPOPENFILENAME lpofn; char tmpstr[512], tmpstr2[512]; LPSTR pstr, pstr2; + UINT control,notification; + + /* Notifications are packaged differently in Win32 */ +#ifdef WINELIB32 + control = LOWORD(wParam); + notification = HIWORD(wParam); +#else + control = wParam; + notification = HIWORD(lParam); +#endif lpofn = (LPOPENFILENAME)GetWindowLong(hWnd, DWL_USER); - switch (wParam) + switch (control) { case lst1: /* file list */ FILEDLG_StripEditControl(hWnd); - if (HIWORD(lParam) == LBN_DBLCLK) + if (notification == LBN_DBLCLK) goto almost_ok; lRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0); if (lRet == LB_ERR) return TRUE; @@ -394,7 +405,7 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) return TRUE; case lst2: /* directory list */ FILEDLG_StripEditControl(hWnd); - if (HIWORD(lParam) == LBN_DBLCLK) + if (notification == LBN_DBLCLK) { lRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0); if (lRet == LB_ERR) return TRUE; @@ -410,7 +421,7 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) } return TRUE; case cmb1: /* file type drop list */ - if (HIWORD(lParam) == CBN_SELCHANGE) + if (notification == CBN_SELCHANGE) { *tmpstr = 0; goto reset_scan; @@ -494,12 +505,11 @@ static LRESULT FILEDLG_WMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, (LPARAM)MAKE_SEGPTR(tmpstr)); ShowWindow(hWnd, SW_HIDE); { - int drive; - drive = DOS_GetDefaultDrive(); + int drive = DRIVE_GetCurrentDrive(); tmpstr2[0] = 'A'+ drive; tmpstr2[1] = ':'; tmpstr2[2] = '\\'; - strncpy(tmpstr2 + 3, DOS_GetCurrentDir(drive), 507); tmpstr2[510]=0; + strncpy(tmpstr2 + 3, DRIVE_GetDosCwd(drive), 507); tmpstr2[510]=0; if (strlen(tmpstr2) > 3) strcat(tmpstr2, "\\"); strncat(tmpstr2, tmpstr, 511-strlen(tmpstr2)); tmpstr2[511]=0; diff --git a/misc/dos_fs.c b/misc/dos_fs.c index 6235df63f38..b01f6b01770 100644 --- a/misc/dos_fs.c +++ b/misc/dos_fs.c @@ -40,77 +40,6 @@ #include "xmalloc.h" #define WINE_INI_USER "~/.winerc" -#define MAX_DOS_DRIVES 26 - -extern char WindowsDirectory[256], SystemDirectory[256],TempDirectory[256]; - -char WindowsPath[256]; - -static int CurrentDrive = 2; - -struct DosDriveStruct { /* eg: */ - char *rootdir; /* /usr/windows */ - char cwd[256]; /* / */ - char label[13]; /* DRIVE-A */ - unsigned int serialnumber; /* ABCD5678 */ - int disabled; /* 0 */ -}; - -static struct DosDriveStruct DosDrives[MAX_DOS_DRIVES]; -static struct dosdirent *DosDirs=NULL; - -WORD ExtendedError; -BYTE ErrorClass, Action, ErrorLocus; - -int DOS_Error(int e, int class, int el) -{ - ErrorClass = class; - Action = SA_Ask4Retry; - ErrorLocus = el; - ExtendedError = e; - - return e; -} - -void errno_to_doserr(void) -{ - switch (errno) { - case EAGAIN: - DOS_Error (ShareViolation, EC_Temporary, EL_Unknown); - break; - case EBADF: - DOS_Error (InvalidHandle, EC_AppError, EL_Unknown); - break; - case ENOSPC: - DOS_Error (DiskFull, EC_MediaError, EL_Disk); - break; - case EACCES: - case EPERM: - case EROFS: - DOS_Error (WriteProtected, EC_AccessDenied, EL_Unknown); - break; - case EBUSY: - DOS_Error (LockViolation, EC_AccessDenied, EL_Unknown); - break; - case ENOENT: - DOS_Error (FileNotFound, EC_NotFound, EL_Unknown); - break; - case EISDIR: - DOS_Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown); - break; - case ENFILE: - case EMFILE: - DOS_Error (NoMoreFiles, EC_MediaError, EL_Unknown); - break; - case EEXIST: - DOS_Error (FileExists, EC_Exists, EL_Disk); - break; - default: - dprintf_int(stddeb, "int21: unknown errno %d!\n", errno); - DOS_Error (GeneralFailure, EC_SystemFailure, EL_Unknown); - break; - } -} static void ExpandTildeString(char *s) @@ -141,503 +70,22 @@ static void ExpandTildeString(char *s) *s = 0; } -/* Simplify the path in "name" by removing "//"'s, "/./"'s, and - ".."'s in names like "/usr/bin/../lib/test" */ -static void DOS_SimplifyPath(char *name) -{ - char *l,*p; - BOOL changed; - dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name); - do { - changed = FALSE; - while ((l = strstr(name,"//"))) { - strcpy(l,l+1); changed = TRUE; - } - while ((l = strstr(name,"/../"))) { - *l = 0; - p = strrchr(name,'/'); - if (p == NULL) p = name; - strcpy(p,l+3); - changed = TRUE; - } - while ((l = strstr(name, "/./"))) { - strcpy(l, l+2); changed = TRUE; - } - } while (changed); - dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name); -} - - -/* ChopOffSlash takes care to strip directory slashes from the - * end off the path name, but leaves a single slash. Multiple - * slashes at the end of a path are all removed. - */ - -void ChopOffSlash(char *path) -{ - char *p = path + strlen(path) - 1; - while ((*p == '\\') && (p > path)) *p-- = '\0'; -} - -void ToUnix(char *s) -{ - while(*s){ - if (*s == '\\') *s = '/'; - *s=tolower(*s); /* umsdos fs can't read files without :( */ - s++; - } -} - -void ToDos(char *s) -{ - while(*s){ - if (*s == '/') *s = '\\'; - s++; - } -} - -void DOS_InitFS(void) -{ - int x; - char drive[2], temp[256]; - struct dosdirent *dp; - GetPrivateProfileString("wine", "windows", "c:\\windows", - WindowsDirectory, sizeof(WindowsDirectory), WINE_INI); - - GetPrivateProfileString("wine", "system", "c:\\windows\\system", - SystemDirectory, sizeof(SystemDirectory), WINE_INI); - - GetPrivateProfileString("wine", "temp", "c:\\windows", - TempDirectory, sizeof(TempDirectory), WINE_INI); - - GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", - WindowsPath, sizeof(WindowsPath), WINE_INI); - - ChopOffSlash(WindowsDirectory); - ToDos(WindowsDirectory); - - ChopOffSlash(SystemDirectory); - ToDos(SystemDirectory); - - ChopOffSlash(TempDirectory); - ToDos(TempDirectory); - - ToDos(WindowsPath); - ExpandTildeString(WindowsPath); - - for (x=0; x!=MAX_DOS_DRIVES; x++) { - DosDrives[x].serialnumber = (0xEB0500L | x); - - drive[0] = 'A' + x; - drive[1] = '\0'; - GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI); - if (!strcmp(temp, "*") || *temp == '\0') { - DosDrives[x].rootdir = NULL; - DosDrives[x].cwd[0] = '\0'; - DosDrives[x].label[0] = '\0'; - DosDrives[x].disabled = 1; - continue; - } - ExpandTildeString(temp); - ChopOffSlash(temp); - DosDrives[x].rootdir = strdup(temp); - strcpy(DosDrives[x].rootdir, temp); - strcpy(DosDrives[x].cwd, "/windows/"); - strcpy(DosDrives[x].label, "DRIVE-"); - strcat(DosDrives[x].label, drive); - DosDrives[x].disabled = 0; - } - DosDrives[25].rootdir = "/"; - strcpy(DosDrives[25].label, "UNIX-FS"); - DosDrives[25].serialnumber = 0x12345678; - DosDrives[25].disabled = 0; - - /* Get the startup directory and try to map it to a DOS drive - * and directory. (i.e., if we start in /dos/windows/word and - * drive C is defined as /dos, the starting wd for C will be - * /windows/word) Also set the default drive to whatever drive - * corresponds to the directory we started in. - */ - - for (x=0; x!=MAX_DOS_DRIVES; x++) - if (DosDrives[x].rootdir != NULL) - strcpy( DosDrives[x].cwd, "/" ); - - getcwd(temp, 254); - strcat(temp, "/"); /* For DOS_GetDosFileName */ - strcpy(DosDrives[25].cwd, temp ); - strcpy(temp, DOS_GetDosFileName(temp)); - if(temp[0] != 'Z') - { - ToUnix(temp + 2); - strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]); - DOS_SetDefaultDrive(temp[0] - 'A'); - } - else - { - DOS_SetDefaultDrive(2); - } - - for (x=0; x!=MAX_DOS_DRIVES; x++) { - if (DosDrives[x].rootdir != NULL) { - dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n", - 'A'+x, - DosDrives[x].rootdir, - DosDrives[x].cwd, - DosDrives[x].label, - DosDrives[x].serialnumber, - DosDrives[x].disabled); - } - } - dp = DosDirs; - while (dp) - { - dp->inuse = 0; - dp = dp->next; - } - - dprintf_dosfs(stddeb,"wine.ini = %s\n",WINE_INI); - dprintf_dosfs(stddeb,"win.ini = %s\n",WIN_INI); - dprintf_dosfs(stddeb,"windir = %s\n",WindowsDirectory); - dprintf_dosfs(stddeb,"sysdir = %s\n",SystemDirectory); - dprintf_dosfs(stddeb,"tempdir = %s\n",TempDirectory); - dprintf_dosfs(stddeb,"path = %s\n",WindowsPath); -} - -WORD DOS_GetEquipment(void) -{ - WORD equipment; - int diskdrives = 0; - int parallelports = 0; - int serialports = 0; - int x; - -/* borrowed from Ralph Brown's interrupt lists - - bits 15-14: number of parallel devices - bit 13: [Conv] Internal modem - bit 12: reserved - bits 11- 9: number of serial devices - bit 8: reserved - bits 7- 6: number of diskette drives minus one - bits 5- 4: Initial video mode: - 00b = EGA,VGA,PGA - 01b = 40 x 25 color - 10b = 80 x 25 color - 11b = 80 x 25 mono - bit 3: reserved - bit 2: [PS] =1 if pointing device - [non-PS] reserved - bit 1: =1 if math co-processor - bit 0: =1 if diskette available for boot -*/ -/* Currently the only of these bits correctly set are: - bits 15-14 } Added by William Owen Smith, - bits 11-9 } wos@dcs.warwick.ac.uk - bits 7-6 - bit 2 (always set) -*/ - - if (DosDrives[0].rootdir != NULL) - diskdrives++; - if (DosDrives[1].rootdir != NULL) - diskdrives++; - if (diskdrives) - diskdrives--; - - for (x=0; x!=MAX_PORTS; x++) { - if (COM[x].devicename) - serialports++; - if (LPT[x].devicename) - parallelports++; - } - if (serialports > 7) /* 3 bits -- maximum value = 7 */ - serialports=7; - if (parallelports > 3) /* 2 bits -- maximum value = 3 */ - parallelports=3; - - equipment = (diskdrives << 6) | (serialports << 9) | - (parallelports << 14) | 0x02; - - dprintf_dosfs(stddeb, "DOS_GetEquipment : diskdrives = %d serialports = %d " - "parallelports = %d\n" - "DOS_GetEquipment : equipment = %d\n", - diskdrives, serialports, parallelports, equipment); - - return equipment; -} - -int DOS_ValidDrive(int drive) -{ - dprintf_dosfs(stddeb,"ValidDrive %c (%d)\n",'A'+drive,drive); - - if (drive < 0 || drive >= MAX_DOS_DRIVES) return 0; - if (DosDrives[drive].rootdir == NULL) return 0; - if (DosDrives[drive].disabled) return 0; - - dprintf_dosfs(stddeb, " -- valid\n"); - return 1; -} - -static void DOS_GetCurrDir_Unix(char *buffer, int drive) -{ - TDB *pTask = (TDB *)GlobalLock(GetCurrentTask()); - - if (pTask != NULL && (pTask->curdrive & ~0x80) == drive) { - strcpy(buffer, pTask->curdir); - ToUnix(buffer); - } else { - strcpy(buffer, DosDrives[drive].cwd); - } -} - -char *DOS_GetCurrentDir(int drive) -{ - static char temp[256]; - - if (!DOS_ValidDrive(drive)) return 0; - - DOS_GetCurrDir_Unix(temp, drive); - DOS_SimplifyPath( temp ); - ToDos(temp); - ChopOffSlash(temp); - - dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp); - return temp + 1; -} - -char *DOS_GetUnixFileName(const char *dosfilename) -{ - /* a:\windows\system.ini => /dos/windows/system.ini */ - - /* FIXME: should handle devices here (like LPT: or NUL:) */ - - static char dostemp[256], temp[256]; - int drive = DOS_GetDefaultDrive(); - - if (dosfilename[0] && dosfilename[1] == ':') - { - drive = toupper(*dosfilename) - 'A'; - dosfilename += 2; - } - if (!DOS_ValidDrive(drive)) return NULL; - - strncpy( dostemp, dosfilename, 255 ); - dostemp[255] = 0; - ToUnix(dostemp); - strcpy(temp, DosDrives[drive].rootdir); - if (dostemp[0] != '/') { - DOS_GetCurrDir_Unix(temp+strlen(temp), drive); - } - strcat(temp, dostemp); - DOS_SimplifyPath(temp); - - dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp); - return temp; -} - -/* Note: This function works on directories as well as long as - * the directory ends in a slash. - */ -char *DOS_GetDosFileName(char *unixfilename) -{ - int i; - static char temp[256], temp2[256]; - /* /dos/windows/system.ini => c:\windows\system.ini */ - - dprintf_dosfs(stddeb,"DOS_GetDosFileName: %s\n", unixfilename); - if (unixfilename[0] == '/') { - strncpy(temp, unixfilename, 255); - temp[255] = 0; - } else { - /* Expand it if it's a relative name. */ - getcwd(temp, 255); - if(strncmp(unixfilename, "./", 2) == 0) { - strcat(temp, unixfilename + 1); - } else { - strcat(temp, "/"); - strcat(temp, unixfilename); - } - } - for (i = 0 ; i < MAX_DOS_DRIVES; i++) { - if (DosDrives[i].rootdir != NULL) { - int len = strlen(DosDrives[i].rootdir); - dprintf_dosfs(stddeb, " check %c:%s\n", i+'A', DosDrives[i].rootdir); - if (strncmp(DosDrives[i].rootdir, temp, len) == 0 && temp[len] == '/') - { - sprintf(temp2, "%c:%s", 'A' + i, temp+len); - ToDos(temp2+2); - return temp2; - } - } - } - sprintf(temp, "Z:%s", unixfilename); - ToDos(temp+2); - return temp; -} - -int DOS_ValidDirectory(int drive, char *name) -{ - char temp[256]; - struct stat s; - - strcpy(temp, DosDrives[drive].rootdir); - strcat(temp, name); - if (stat(temp, &s)) return 0; - if (!S_ISDIR(s.st_mode)) return 0; - dprintf_dosfs(stddeb, "==> OK\n"); - return 1; -} - -int DOS_GetDefaultDrive(void) -{ - TDB *pTask = (TDB *)GlobalLock(GetCurrentTask()); - int drive = pTask == NULL ? CurrentDrive : pTask->curdrive & ~0x80; - - dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+drive); - return drive; -} - -void DOS_SetDefaultDrive(int drive) -{ - TDB *pTask = (TDB *)GlobalLock(GetCurrentTask()); - - dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive); - if (DOS_ValidDrive(drive) && drive != DOS_GetDefaultDrive()) { - if (pTask == NULL) CurrentDrive = drive; - else { - char temp[256]; - pTask->curdrive = drive | 0x80; - strcpy(temp, DosDrives[drive].rootdir); - strcat(temp, DosDrives[drive].cwd); - strcpy(temp, DOS_GetDosFileName(temp)); - dprintf_dosfs(stddeb, " curdir = %s\n", temp); - if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2); - else fprintf(stderr, "dosfs: curdir too long\n"); - } - } -} - -int DOS_DisableDrive(int drive) -{ - if (drive >= MAX_DOS_DRIVES) return 0; - if (DosDrives[drive].rootdir == NULL) return 0; - - DosDrives[drive].disabled = 1; - return 1; -} - -int DOS_EnableDrive(int drive) -{ - if (drive >= MAX_DOS_DRIVES) return 0; - if (DosDrives[drive].rootdir == NULL) return 0; - - DosDrives[drive].disabled = 0; - return 1; -} - -int DOS_ChangeDir(int drive, char *dirname) -{ - TDB *pTask = (TDB *)GlobalLock(GetCurrentTask()); - char temp[256]; - - if (!DOS_ValidDrive(drive)) return 0; - - if (dirname[0] == '\\') { - strcpy(temp, dirname); - } else { - DOS_GetCurrDir_Unix(temp, drive); - strcat(temp, dirname); - } - ToUnix(temp); - strcat(temp, "/"); - DOS_SimplifyPath(temp); - dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s ==> %s\n", 'A'+drive, dirname, temp); - - if (!DOS_ValidDirectory(drive, temp)) return 0; - strcpy(DosDrives[drive].cwd, temp); - if (pTask != NULL && DOS_GetDefaultDrive() == drive) { - strcpy(temp, DosDrives[drive].rootdir); - strcat(temp, DosDrives[drive].cwd); - strcpy(temp, DOS_GetDosFileName(temp)); - dprintf_dosfs(stddeb, " curdir = %s\n", temp); - if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2); - else fprintf(stderr, "dosfs: curdir too long\n"); - } - return 1; -} - -int DOS_MakeDir(int drive, char *dirname) -{ - char temp[256], currdir[256]; - - if (!DOS_ValidDrive(drive)) return 0; - - strcpy(temp, DosDrives[drive].rootdir); - DOS_GetCurrDir_Unix(currdir, drive); - strcat(temp, currdir); - strcat(temp, dirname); - ToUnix(temp); - DOS_SimplifyPath(temp); - if (mkdir(temp, S_IRWXU | S_IRWXG | S_IRWXO) == -1) - { - dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s failed errno %d",'A'+drive, dirname, temp, errno); - return 0; - } - dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp); - return 1; -} - -int DOS_GetSerialNumber(int drive, unsigned long *serialnumber) -{ - if (!DOS_ValidDrive(drive)) - return 0; - - *serialnumber = DosDrives[drive].serialnumber; - return 1; -} - -int DOS_SetSerialNumber(int drive, unsigned long serialnumber) -{ - if (!DOS_ValidDrive(drive)) - return 0; - - DosDrives[drive].serialnumber = serialnumber; - return 1; -} - -char *DOS_GetVolumeLabel(int drive) -{ - if (!DOS_ValidDrive(drive)) - return NULL; - - return DosDrives[drive].label; -} - -int DOS_SetVolumeLabel(int drive, char *label) -{ - if (!DOS_ValidDrive(drive)) - return 0; - - strncpy(DosDrives[drive].label, label, 8); - return 1; -} int DOS_GetFreeSpace(int drive, long *size, long *available) { - struct statfs info; + struct statfs info; + const char *root; - if (!DOS_ValidDrive(drive)) - return 0; + if (!DRIVE_IsValid(drive)) return 0; + root = DRIVE_GetRoot(drive); #ifdef __svr4__ - if (statfs(DosDrives[drive].rootdir, &info, 0, 0) < 0) { + if (statfs( root, &info, 0, 0) < 0) { #else - if (statfs(DosDrives[drive].rootdir, &info) < 0) { + if (statfs( root, &info) < 0) { #endif - fprintf(stderr,"dosfs: cannot do statfs(%s)\n", - DosDrives[drive].rootdir); + fprintf(stderr,"dosfs: cannot do statfs(%s)\n", root ); return 0; } @@ -647,91 +95,9 @@ int DOS_GetFreeSpace(int drive, long *size, long *available) #else *available = info.f_bavail * info.f_bsize; #endif - return 1; } -char *DOS_FindFile(char *buffer, int buflen, const char *filename, char **extensions, - char *path) -{ - char *workingpath, *dirname, *rootname, **e; - DIR *d; - struct dirent *f; - int rootnamelen; - struct stat filestat; - - if (strchr(filename, '\\') != NULL) - { - strncpy(buffer, DOS_GetUnixFileName(filename), buflen); - stat( buffer, &filestat); - if (S_ISREG(filestat.st_mode)) - return buffer; - else - return NULL; - } - - if (strchr(filename, '/') != NULL) - { - strncpy(buffer, filename, buflen); - return buffer; - } - - dprintf_dosfs(stddeb,"DOS_FindFile: looking for %s\n", filename); - rootnamelen = strlen(filename); - rootname = strdup(filename); - ToUnix(rootname); - workingpath = strdup(path); - - for(dirname = strtok(workingpath, ";"); - dirname != NULL; - dirname = strtok(NULL, ";")) - { - if (strchr(dirname, '\\') != NULL) - d = opendir( DOS_GetUnixFileName(dirname) ); - else - d = opendir( dirname ); - - dprintf_dosfs(stddeb,"in %s\n",dirname); - if (d != NULL) - { - while ((f = readdir(d)) != NULL) - { - if (strcasecmp(rootname, f->d_name) != 0) { - if (strncasecmp(rootname, f->d_name, rootnamelen) != 0 - || extensions == NULL - || f->d_name[rootnamelen] != '.') - continue; - - for (e = extensions; *e != NULL; e++) { - if (strcasecmp(*e, f->d_name + rootnamelen + 1) == 0) - break; - } - if (*e == NULL) continue; - } - - if (strchr(dirname, '\\') != NULL) { - strncpy(buffer, DOS_GetUnixFileName(dirname), buflen); - } else { - strncpy(buffer, dirname, buflen); - } - - strncat(buffer, "/", buflen - strlen(buffer)); - strncat(buffer, f->d_name, buflen - strlen(buffer)); - - stat(buffer, &filestat); - if (S_ISREG(filestat.st_mode)) { - closedir(d); - free(rootname); - DOS_SimplifyPath(buffer); - return buffer; - } - } - closedir(d); - } - } - return NULL; -} - /********************************************************************** * WineIniFileName */ @@ -761,210 +127,3 @@ char *WineIniFileName(void) exit(1); } -char *WinIniFileName(void) -{ - static char *name = NULL; - - if (name) - return name; - - name = xmalloc(1024); - - strcpy(name, DOS_GetUnixFileName(WindowsDirectory)); - strcat(name, "/"); - strcat(name, "win.ini"); - - name = xrealloc(name, strlen(name) + 1); - - return name; -} - -static int match(char *filename, char *filemask) -{ - char name[12], mask[12]; - int i; - - dprintf_dosfs(stddeb, "match: %s, %s\n", filename, filemask); - - for( i=0; i<11; i++ ) { - name[i] = ' '; - mask[i] = ' '; - } - name[11] = 0; - mask[11] = 0; - - for( i=0; i<8; i++ ) - if( !(*filename) || *filename == '.' ) - break; - else - name[i] = toupper( *filename++ ); - while( *filename && *filename != '.' ) - filename++; - if( *filename ) - filename++; - for( i=8; i<11; i++ ) - if( !(*filename) ) - break; - else - name[i] = toupper( *filename++ ); - - for( i=0; i<8; i++ ) - if( !(*filemask) || *filemask == '.' ) - break; - else if( *filemask == '*' ) { - int j; - for( j=i; j<8; j++ ) - mask[j] = '?'; - break; - } - else - mask[i] = toupper( *filemask++ ); - while( *filemask && *filemask != '.' ) - filemask++; - if( *filemask ) - filemask++; - for( i=8; i<11; i++ ) - if( !(*filemask) ) - break; - else if (*filemask == '*' ) { - int j; - for( j=i; j<11; j++ ) - mask[j] = '?'; - break; - } - else - mask[i] = toupper( *filemask++ ); - - dprintf_dosfs(stddeb, "changed to: %s, %s\n", name, mask); - - for( i=0; i<11; i++ ) - if( ( name[i] != mask[i] ) && ( mask[i] != '?' ) ) - return 0; - - return 1; -} - -struct dosdirent *DOS_opendir(char *dosdirname) -{ - int len; - char *unixdirname; - char dirname[256]; - DIR *ds; - struct dosdirent *dp; - - if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL) return NULL; - - len = strrchr(unixdirname, '/') - unixdirname + 1; - strncpy(dirname, unixdirname, len); - dirname[len] = 0; - unixdirname = strrchr(unixdirname, '/') + 1; - if ((ds = opendir(dirname)) == NULL) - return NULL; - - dp = DosDirs; - while (dp) - { - if (dp->inuse) - break; - if (strcmp(dp->unixpath, dirname) == 0) - break; - dp = dp->next; - } - if (!dp) - { - dp = xmalloc(sizeof(struct dosdirent)); - dp->next = DosDirs; - DosDirs = dp; - } - - strncpy(dp->filemask, unixdirname, 12); - dp->filemask[12] = 0; - dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, dirname); - - dp->inuse = 1; - strcpy(dp->unixpath, dirname); - dp->entnum = 0; - - if (closedir(ds) == -1) - { - dp->inuse = 0; - return NULL; - } - return dp; -} - - -struct dosdirent *DOS_readdir(struct dosdirent *de) -{ - char temp[WINE_PATH_LENGTH]; - struct dirent *d; - struct stat st; - DIR *ds; - int i; - - if (!de->inuse) - return NULL; - if (!(ds=opendir(de->unixpath))) return NULL; - /* skip all already read directory entries. - * the dir has hopefully not been modified in the meantime - */ - for (i=de->entnum;i--;) - readdir(ds); - - if (de->search_attribute & FA_LABEL) { - int drive; - de->search_attribute &= ~FA_LABEL; /* don't find it again */ - for(drive = 0; drive < MAX_DOS_DRIVES; drive++) { - if (DosDrives[drive].rootdir != NULL && - strcmp(DosDrives[drive].rootdir, de->unixpath) == 0) - { - strcpy(de->filename, DOS_GetVolumeLabel(drive)); - de->attribute = FA_LABEL; - return de; - } - } - } - - do { - de->entnum++; /* Increment the directory entry number */ - if ((d = readdir(ds)) == NULL) { - closedir(ds); - return NULL; - } - strcpy(de->filename, d->d_name); - if (d->d_reclen > 12) - de->filename[12] = '\0'; - ToDos(de->filename); - - strcpy(temp,de->unixpath); - strcat(temp,"/"); - strcat(temp,d->d_name); - stat (temp, &st); - de->attribute = 0x0; - if S_ISDIR(st.st_mode) - de->attribute |= FA_DIREC; - - } while (!(de->attribute & FA_DIREC) && - !match(de->filename, de->filemask) ); - - - de->filesize = st.st_size; - de->filetime = st.st_mtime; - - closedir(ds); - return de; -} - -void DOS_closedir(struct dosdirent *de) -{ - if (de && de->inuse) - de->inuse = 0; -} - -char *DOS_GetRedirectedDir(int drive) -{ - if(DOS_ValidDrive(drive)) - return (DosDrives[drive].rootdir); - else - return ("/"); -} diff --git a/misc/file.c b/misc/file.c deleted file mode 100644 index 888701a46e5..00000000000 --- a/misc/file.c +++ /dev/null @@ -1,468 +0,0 @@ -/************************************************************************ - * FILE.C Copyright (C) 1993 John Burton - * - * File I/O routines for the Linux Wine Project. - * - * WARNING : Many options of OpenFile are not yet implemeted. - * - * NOV 93 Erik Bos (erik@xs4all.nl) - * - removed ParseDosFileName, and DosDrive structures. - * - structures dynamically configured at runtime. - * - _lopen modified to use DOS_GetUnixFileName. - * - Existing functions modified to use dosfs functions. - * - Added _llseek, _lcreat, GetDriveType, GetTempDrive, - * GetWindowsDirectory, GetSystemDirectory, GetTempFileName. - * - ************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include "dos_fs.h" -#include "windows.h" -#include "msdos.h" -#include "options.h" -#include "stddebug.h" -#include "debug.h" - -#define MAX_PATH 255 - -char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256]; - -/*************************************************************************** - _lopen - - Emulate the _lopen windows call - ***************************************************************************/ -INT _lopen (LPSTR lpPathName, INT iReadWrite) -{ - int handle; - char *UnixFileName; - int mode = 0; - - dprintf_file(stddeb, "_lopen: open('%s', %X);\n", lpPathName, iReadWrite); - if ((UnixFileName = DOS_GetUnixFileName(lpPathName)) == NULL) - return HFILE_ERROR; - switch(iReadWrite & 3) - { - case OF_READ: mode = O_RDONLY; break; - case OF_WRITE: mode = O_WRONLY | O_TRUNC; break; - case OF_READWRITE: mode = O_RDWR; break; - } - handle = open( UnixFileName, mode ); - if (( handle == -1 ) && Options.allowReadOnly) - handle = open( UnixFileName, O_RDONLY ); - - dprintf_file(stddeb, "_lopen: open: %s (handle %d)\n", UnixFileName, handle); - - if (handle == -1) - return HFILE_ERROR; - else - return handle; -} - -/*************************************************************************** - _lread - ***************************************************************************/ -INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes) -{ - int result; - - dprintf_file(stddeb, "_lread: handle %d, buffer = %p, length = %d\n", - hFile, lpBuffer, wBytes); - - result = (wBytes == 0) ? 0 : read (hFile, lpBuffer, wBytes); - - if (result == -1) - return HFILE_ERROR; - else - return result; -} - -/**************************************************************************** - _lwrite -****************************************************************************/ -INT _lwrite (INT hFile, LPCSTR lpBuffer, WORD wBytes) -{ - int result; - - dprintf_file(stddeb, "_lwrite: handle %d, buffer = %p, length = %d\n", - hFile, lpBuffer, wBytes); - - if(wBytes == 0) { /* Expand the file size if necessary */ - char toWrite = 0; - off_t prev, end; - - prev = lseek(hFile, 0, SEEK_CUR); - if(prev == -1) return HFILE_ERROR; - end = lseek(hFile, 0, SEEK_END); - if(end == -1) return HFILE_ERROR; - if(prev > end) { - lseek(hFile, prev-1, SEEK_SET); - result = write(hFile, &toWrite, 1) - 1; - if(result == -2) ++result; - } - else { - lseek(hFile, prev, SEEK_SET); - result = 0; - } - } - else result = write (hFile, lpBuffer, wBytes); - - if (result == -1) - return HFILE_ERROR; - else - return result; -} - -/*************************************************************************** - _lclose - ***************************************************************************/ -INT _lclose (INT hFile) -{ - dprintf_file(stddeb, "_lclose: handle %d\n", hFile); - - if (hFile == 0 || hFile == 1 || hFile == 2) { - fprintf( stderr, "Program attempted to close stdin, stdout or stderr!\n" ); - return 0; - } - if (close (hFile)) - return HFILE_ERROR; - else - return 0; -} - -/************************************************************************** - OpenFile - **************************************************************************/ -INT OpenFile (LPCSTR lpFileName, LPOFSTRUCT ofs, UINT wStyle) -{ - char filename[MAX_PATH+1]; - int action; - struct stat s; - struct tm *now; - int res, handle; - int verify_time = 0; - - dprintf_file(stddeb,"Openfile(%s,,%X)\n",lpFileName,wStyle); - - action = wStyle & 0xff00; - - /* OF_CREATE is completly different from all other options, so - handle it first */ - - if (action & OF_CREATE) - { - char *unixfilename; - - if (!(action & OF_REOPEN)) strcpy(ofs->szPathName, lpFileName); - ofs->cBytes = sizeof(OFSTRUCT); - ofs->fFixedDisk = FALSE; - ofs->nErrCode = 0; - *((int*)ofs->reserved) = 0; - - if ((unixfilename = DOS_GetUnixFileName (ofs->szPathName)) == NULL) - { - errno_to_doserr(); - ofs->nErrCode = ExtendedError; - return -1; - } - /* Apparently, at least the OF_READ parameter is ignored when - * a file is created. Using O_RDWR makes the most sense. - */ - handle = open (unixfilename, O_TRUNC | O_RDWR | O_CREAT, 0666); - if (handle == -1) - { - errno_to_doserr(); - ofs->nErrCode = ExtendedError; - } - return handle; - } - - - /* If path isn't given, try to find the file. */ - - if (!(action & OF_REOPEN)) - { - char temp[MAX_PATH + 1]; - - if(index(lpFileName,'\\') || index(lpFileName,'/') || - index(lpFileName,':')) - { - strcpy (filename,lpFileName); - goto found; - } - /* Try current directory */ - if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, ".")) { - strcpy(filename, DOS_GetDosFileName(temp)); - goto found; - } - - /* Try Windows directory */ - GetWindowsDirectory(filename, MAX_PATH); - if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) { - strcpy(filename, DOS_GetDosFileName(temp)); - goto found; - } - - /* Try Windows system directory */ - GetSystemDirectory(filename, MAX_PATH); - if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) { - strcpy(filename, DOS_GetDosFileName(temp)); - goto found; - } - - /* Try the path of the current executable */ - if (GetCurrentTask()) - { - char *p; - GetModuleFileName( GetCurrentTask(), filename, MAX_PATH ); - if ((p = strrchr( filename, '\\' ))) - { - p[1] = '\0'; - if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) { - strcpy(filename, DOS_GetDosFileName(temp)); - goto found; - } - } - } - - /* Try all directories in path */ - - if (DOS_FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath)) - { - strcpy(filename, DOS_GetDosFileName(temp)); - goto found; - } - /* ??? shouldn't we give an error here? */ - strcpy (filename, lpFileName); - - found: - - ofs->cBytes = sizeof(OFSTRUCT); - ofs->fFixedDisk = FALSE; - strcpy(ofs->szPathName, filename); - ofs->nErrCode = 0; - if (!(action & OF_VERIFY)) - *((int*)ofs->reserved) = 0; - } - - - if (action & OF_PARSE) - return 0; - - if (action & OF_DELETE) - return unlink(DOS_GetUnixFileName(ofs->szPathName)); - /* FIXME: I suppose we should check return codes here like stat below */ - - /* Now on to getting some information about that file */ - - if ((res = stat(DOS_GetUnixFileName(ofs->szPathName), &s))) - { - errno_to_doserr(); - ofs->nErrCode = ExtendedError; - return -1; - } - - now = localtime (&s.st_mtime); - - if (action & OF_VERIFY) - verify_time = *((int*)ofs->reserved); - - *((WORD*)(&ofs->reserved[2]))= - ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2)); - *((WORD*)(&ofs->reserved[0]))= - ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday); - - if (action & OF_VERIFY) - return (verify_time != *((int*)ofs->reserved)); - - if ((handle = _lopen( ofs->szPathName, wStyle )) == -1) - { - ofs->nErrCode = 2; /* not found */ - return -1; - } - if (action & OF_EXIST) close(handle); - return handle; -} - - -/************************************************************************** - SetHandleCount - - Changes the number of file handles available to the application. Since - Linux isn't limited to 20 files, this one's easy. - SL - **************************************************************************/ - -#if !defined (OPEN_MAX) -/* This one is for the Sun */ -#define OPEN_MAX _POSIX_OPEN_MAX -#endif -WORD SetHandleCount (WORD wNumber) -{ - dprintf_file(stddeb,"SetHandleCount(%d)\n",wNumber); - return((wNumber %s\n",bDriveLetter, - lpszPrefixString,uUnique,lpszTempFileName); - if ((handle = _lcreat (lpszTempFileName, 0x0000)) == -1) { - fprintf(stderr,"GetTempFilename: can't create temp file '%s' !\n", lpszTempFileName); - } - else - close(handle); - - return unique; -} - -/*************************************************************************** - SetErrorMode - ***************************************************************************/ -WORD SetErrorMode(WORD x) -{ - dprintf_file(stdnimp,"wine: SetErrorMode %4x (ignored)\n",x); - - return 1; -} - -/*************************************************************************** - _hread - ***************************************************************************/ -LONG _hread(INT hf, LPSTR hpvBuffer, LONG cbBuffer) -{ - return (cbBuffer == 0) ? 0 : read(hf, hpvBuffer, cbBuffer); -} -/*************************************************************************** - _hwrite - ***************************************************************************/ -LONG _hwrite(INT hf, LPCSTR hpvBuffer, LONG cbBuffer) -{ - return (cbBuffer == 0) ? 0 : write(hf, hpvBuffer, cbBuffer); -} diff --git a/misc/lstr.c b/misc/lstr.c index 5d03363441f..5f7c90adde4 100644 --- a/misc/lstr.c +++ b/misc/lstr.c @@ -66,17 +66,36 @@ SEGPTR lstrcat( SEGPTR target, SEGPTR source ) /* USER.430 */ INT lstrcmp(LPCSTR str1,LPCSTR str2) { - return strcmp(str1,str2); + return strcmp( str1, str2 ); } /* USER.471 */ -INT lstrcmpi(LPCSTR str1,LPCSTR str2) +INT lstrcmpi( LPCSTR str1, LPCSTR str2 ) { - int i; - i=0; - while((toupper(str1[i])==toupper(str2[i]))&&(str1[i]!=0)) - i++; - return toupper(str1[i])-toupper(str2[i]); + INT res; + + while (*str1) + { + if ((res = toupper(*str1) - toupper(*str2)) != 0) return res; + str1++; + str2++; + } + return toupper(*str1) - toupper(*str2); +} + +/* Not a Windows API*/ +INT lstrncmpi( LPCSTR str1, LPCSTR str2, int n ) +{ + INT res; + + if (!n) return 0; + while ((--n > 0) && *str1) + { + if ((res = toupper(*str1) - toupper(*str2)) != 0) return res; + str1++; + str2++; + } + return toupper(*str1) - toupper(*str2); } /* KERNEL.88 */ @@ -87,13 +106,13 @@ SEGPTR lstrcpy( SEGPTR target, SEGPTR source ) } /* KERNEL.353 32-bit version*/ -char *lstrcpyn(char *dst, char *src, int n) +char *lstrcpyn( char *dst, const char *src, int n ) { char *tmp = dst; while(n-- > 1 && *src) - *dst++ = *src++; - *dst = 0; - return tmp; + *tmp++ = *src++; + *tmp = 0; + return dst; } /* KERNEL.353 16-bit version*/ diff --git a/misc/main.c b/misc/main.c index 9226c084d80..0d9e9481c1f 100644 --- a/misc/main.c +++ b/misc/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #ifdef MALLOC_DEBUGGING @@ -17,9 +18,9 @@ #include #include #include "wine.h" +#include "message.h" #include "msdos.h" #include "windows.h" -#include "miscemu.h" #include "winsock.h" #include "options.h" #include "desktop.h" @@ -226,7 +227,7 @@ BOOL ParseDebugOptions(char *options) l=strchr(options,',')-options; else l=strlen(options); - if (!strncasecmp(options+1,"all",l-1)) + if (!lstrncmpi(options+1,"all",l-1)) { int i; for (i=0;i -#include "stdio.h" -#include "windows.h" -#include "user.h" +#include -#include "msdos.h" -#include "dos_fs.h" +#include "windows.h" +#include "drive.h" #define WN_SUCCESS 0x0000 #define WN_NOT_SUPPORTED 0x0001 @@ -158,29 +156,28 @@ int WNetUnlockQueueData(LPSTR szQueue) int WNetGetConnection(LPSTR lpLocalName, LPSTR lpRemoteName, UINT FAR *cbRemoteName) { - int drive, rc; + const char *path; - if(lpLocalName[1] == ':') + if (lpLocalName[1] == ':') { - drive = toupper(lpLocalName[0]) - 'A'; - if(!DOS_ValidDrive(drive)) - rc = WN_NOT_CONNECTED; - else + int drive = toupper(lpLocalName[0]) - 'A'; + switch(GetDriveType(drive)) { - if(strlen(DOS_GetRedirectedDir(drive)) + 1 > *cbRemoteName) - rc = WN_MORE_DATA; - else - { - strcpy(lpRemoteName, DOS_GetRedirectedDir(drive)); - *cbRemoteName = strlen(lpRemoteName) + 1; - rc = WN_SUCCESS; - } + case DRIVE_CANNOTDETERMINE: + case DRIVE_DOESNOTEXIST: + return WN_BAD_LOCALNAME; + case DRIVE_REMOVABLE: + case DRIVE_FIXED: + return WN_NOT_CONNECTED; + case DRIVE_REMOTE: + path = DRIVE_GetDosCwd(drive); + if (strlen(path) + 1 > *cbRemoteName) return WN_MORE_DATA; + strcpy( lpRemoteName, path ); + *cbRemoteName = strlen(lpRemoteName) + 1; + return WN_SUCCESS; } } - else - rc = WN_BAD_LOCALNAME; - - return rc; + return WN_BAD_LOCALNAME; } /************************************************************************** diff --git a/misc/ole2nls.c b/misc/ole2nls.c index b02fe65a829..8100e5efac1 100644 --- a/misc/ole2nls.c +++ b/misc/ole2nls.c @@ -460,7 +460,7 @@ int CompareStringA(DWORD lcid, DWORD fdwStyle, l2 = (l2==-1)?strlen(s2):l2; len = l1 +#include +#include + +#ifndef HAVE_USLEEP + +unsigned int usleep (unsigned int useconds) +{ + struct timeval delay; + + delay.tv_sec = 0; + delay.tv_usec = useconds; + + (void) select (0, (fd_set *) NULL, (fd_set *) NULL, (fd_set *) NULL, + &delay); + return 0; +} + +#endif /* HAVE_USLEEP */ + + + diff --git a/misc/profile.c b/misc/profile.c index ecd1b72a031..4790c015548 100644 --- a/misc/profile.c +++ b/misc/profile.c @@ -58,7 +58,7 @@ static TSecHeader *is_loaded (char *FileName) TProfile *p = Base; while (p){ - if (!strcasecmp (FileName, p->FileName)){ + if (!lstrcmpi( FileName, p->FileName)){ Current = p; return p->Section; } @@ -67,6 +67,26 @@ static TSecHeader *is_loaded (char *FileName) return 0; } +#define WIN_INI WinIniFileName() + +static char *WinIniFileName(void) +{ + static char *name = NULL; + int len; + const char *unixName; + + if (name) return name; + + len = GetWindowsDirectory( NULL, 0 ) + 9; + name = xmalloc( len ); + GetWindowsDirectory( name, len ); + strcat( name, "/win.ini" ); + if (!(unixName = DOSFS_GetUnixFileName( name, TRUE ))) return NULL; + free( name ); + name = strdup( unixName ); + return name; +} + static char *GetIniFileName(char *name, char *dir) { char temp[256]; @@ -81,7 +101,7 @@ static char *GetIniFileName(char *name, char *dir) } else strcpy(temp, name); - return DOS_GetUnixFileName(temp); + return DOSFS_GetUnixFileName(temp,TRUE); } static TSecHeader *load (char *filename, char **pfullname) @@ -103,26 +123,27 @@ static TSecHeader *load (char *filename, char **pfullname) /* First try it as is */ file = GetIniFileName(filename, ""); - f = fopen(file, "r"); - - if (f == NULL) { - + if (!file || !(f = fopen(file, "r"))) + { if ((purefilename = strrchr( filename, '\\' ))) purefilename++; else if ((purefilename = strrchr( filename, '/' ))) purefilename++; else purefilename = filename; - ToUnix(purefilename); /* Now try the Windows directory */ GetWindowsDirectory(path, sizeof(path)); - file = GetIniFileName(purefilename, path); - dprintf_profile(stddeb,"Trying to load in windows directory file %s\n", - file); - f = fopen(file, "r"); - - if (f == NULL) { /* Try the path of the current executable */ + if ((file = GetIniFileName(purefilename, path))) + { + dprintf_profile(stddeb,"Trying to load in windows directory file %s\n", + file); + f = fopen(file, "r"); + } + else f = NULL; + + if (f == NULL) + { /* Try the path of the current executable */ if (GetCurrentTask()) { @@ -131,30 +152,34 @@ static TSecHeader *load (char *filename, char **pfullname) if ((p = strrchr( path, '\\' ))) { p[0] = '\0'; /* Remove trailing slash */ - file = GetIniFileName(purefilename, path); - dprintf_profile(stddeb, - "Trying to load in current directory%s\n", - file); - f = fopen(file, "r"); + if ((file = GetIniFileName(purefilename, path))) + { + dprintf_profile(stddeb, + "Trying to load in current directory%s\n", + file); + f = fopen(file, "r"); + } } } } if (f == NULL) { /* And now in $HOME/.wine */ - strcpy(file,getenv("HOME")); - strcat(file, "/.wine/"); - strcat(file, purefilename); - dprintf_profile(stddeb,"Trying to load in user-directory %s\n", file); + strcpy(path,getenv("HOME")); + strcat(path, "/.wine/"); + strcat(path, purefilename); + dprintf_profile(stddeb,"Trying to load in user-directory %s\n", path); + file = path; f = fopen(file, "r"); } if (f == NULL) { /* FIXED: we ought to create it now (in which directory?) */ /* lets do it in ~/.wine */ - strcpy(file,getenv("HOME")); - strcat(file, "/.wine/"); - strcat(file, purefilename); - dprintf_profile(stddeb,"Creating %s\n", file); + strcpy(path,getenv("HOME")); + strcat(path, "/.wine/"); + strcat(path, purefilename); + dprintf_profile(stddeb,"Creating %s\n", path); + file = path; f = fopen(file, "w+"); if (f == NULL) { fprintf(stderr, "profile.c: load() can't find file %s\n", filename); @@ -163,7 +188,7 @@ static TSecHeader *load (char *filename, char **pfullname) } } - *pfullname = strdup(file); + *pfullname = xstrdup(file); dprintf_profile(stddeb,"Loading %s\n", file); firstbrace = TRUE; @@ -205,7 +230,7 @@ static TSecHeader *load (char *filename, char **pfullname) *lastnonspc = 0; if (!strlen(CharBuffer)) fprintf(stderr, "warning: empty section name in ini file\n"); - SecHeader->AppName = strdup (CharBuffer); + SecHeader->AppName = xstrdup (CharBuffer); dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer); firstbrace = FALSE; } else if (SecHeader) { @@ -232,7 +257,7 @@ static TSecHeader *load (char *filename, char **pfullname) fprintf(stderr, "warning: empty key name in ini file\n"); SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys)); SecHeader->Keys->link = temp; - SecHeader->Keys->KeyName = strdup (CharBuffer); + SecHeader->Keys->KeyName = xstrdup (CharBuffer); dprintf_profile(stddeb,"%s: key %s\n", file, CharBuffer); @@ -251,7 +276,7 @@ static TSecHeader *load (char *filename, char **pfullname) } } while(bufsize < STRSIZE-1); *lastnonspc = 0; - SecHeader->Keys->Value = strdup (CharBuffer); + SecHeader->Keys->Value = xstrdup (CharBuffer); dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName, SecHeader->Keys->KeyName, SecHeader->Keys->Value); if (c == ';') { @@ -275,8 +300,8 @@ static void new_key (TSecHeader *section, char *KeyName, char *Value) TKeys *key; key = (TKeys *) xmalloc (sizeof (TKeys)); - key->KeyName = strdup (KeyName); - key->Value = strdup (Value); + key->KeyName = xstrdup (KeyName); + key->Value = xstrdup (Value); key->link = section->Keys; section->Keys = key; } @@ -297,7 +322,7 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName, if (!(section = is_loaded (FileName))){ New = (TProfile *) xmalloc (sizeof (TProfile)); New->link = Base; - New->FileName = strdup (FileName); + New->FileName = xstrdup (FileName); New->Section = load (FileName, &New->FullName); New->changed = FALSE; Base = New; @@ -307,7 +332,7 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName, /* Start search */ for (; section; section = section->link){ - if (strcasecmp (section->AppName, AppName)) + if (lstrcmpi(section->AppName, AppName)) continue; /* If no key value given, then list all the keys */ @@ -333,11 +358,11 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName, } for (key = section->Keys; key; key = key->link){ int slen; - if (strcasecmp (key->KeyName, KeyName)) + if (lstrcmpi(key->KeyName, KeyName)) continue; if (set){ free (key->Value); - key->Value = strdup (Default ? Default : ""); + key->Value = xstrdup (Default ? Default : ""); Current->changed=TRUE; return 1; } @@ -362,7 +387,7 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName, /* Non existent section */ if (set){ section = (TSecHeader *) xmalloc (sizeof (TSecHeader)); - section->AppName = strdup (AppName); + section->AppName = xstrdup (AppName); section->Keys = 0; new_key (section, KeyName, Default); section->link = Current->Section; @@ -376,9 +401,9 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName, return 1; } -short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName, - LPSTR Default, LPSTR ReturnedString, - short Size, LPSTR FileName) +short GetPrivateProfileString (LPCSTR AppName, LPCSTR KeyName, + LPCSTR Default, LPSTR ReturnedString, + short Size, LPCSTR FileName) { int v; @@ -391,15 +416,15 @@ short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName, return Size - v; } -int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default, +int GetProfileString (LPCSTR AppName, LPCSTR KeyName, LPCSTR Default, LPSTR ReturnedString, int Size) { return GetPrivateProfileString (AppName, KeyName, Default, - ReturnedString, Size, WIN_INI); + ReturnedString, Size, WIN_INI ); } -WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default, - LPSTR File) +WORD GetPrivateProfileInt (LPCSTR AppName, LPCSTR KeyName, short Default, + LPCSTR File) { static char IntBuf[10]; static char buf[10]; @@ -408,14 +433,14 @@ WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default, /* Check the exact semantic with the SDK */ GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 10, File); - if (!strcasecmp (IntBuf, "true")) + if (!lstrcmpi(IntBuf, "true")) return 1; - if (!strcasecmp (IntBuf, "yes")) + if (!lstrcmpi(IntBuf, "yes")) return 1; return strtoul( IntBuf, NULL, 0 ); } -WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default) +WORD GetProfileInt (LPCSTR AppName, LPCSTR KeyName, int Default) { return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI); } diff --git a/misc/shell.c b/misc/shell.c index 5e50505bb7d..0d486989619 100644 --- a/misc/shell.c +++ b/misc/shell.c @@ -150,11 +150,11 @@ _LoadLevel(FILE *f,LPKEYSTRUCT lpKey,int tabsexp,char *buf) if (NULL!=(t=strchr(s,'='))) { *t='\0';t++; lpNewKey->dwType = REG_SZ; - lpNewKey->lpSubKey = strdup(s); - lpNewKey->lpValue = strdup(t); + lpNewKey->lpSubKey = xstrdup(s); + lpNewKey->lpValue = xstrdup(t); } else { lpNewKey->dwType = REG_SZ; - lpNewKey->lpSubKey = strdup(s); + lpNewKey->lpSubKey = xstrdup(s); } _LoadLevel(f,lpNewKey,tabsexp+1,buf); } @@ -175,11 +175,11 @@ _LoadLevel(FILE *f,LPKEYSTRUCT lpKey,int tabsexp,char *buf) if (NULL!=(t=strchr(s,'='))) { *t='\0';t++; lpNewKey->dwType = REG_SZ; - lpNewKey->lpSubKey = strdup(s); - lpNewKey->lpValue = strdup(t); + lpNewKey->lpSubKey = xstrdup(s); + lpNewKey->lpValue = xstrdup(t); } else { lpNewKey->dwType = REG_SZ; - lpNewKey->lpSubKey = strdup(s); + lpNewKey->lpSubKey = xstrdup(s); } lpKey=lpNewKey; } @@ -280,6 +280,7 @@ LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey) lpKey = lphTopKey; break; case HKEY_CLASSES_ROOT: /* == 1 */ case 0x80000000: + case 0x80000001: lpKey = lphRootKey; break; default: dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", (DWORD)hKey); diff --git a/misc/spy.c b/misc/spy.c index e547e1c023c..3a92d62a0b4 100644 --- a/misc/spy.c +++ b/misc/spy.c @@ -539,7 +539,7 @@ void SpyInit(void) if(MessageTypeNames[i]) if(strstr(lpstrBuffer,MessageTypeNames[i])) SpyFilters[i] = TRUE; - GetPrivateProfileString("spy", "Include", "",lpstrBuffer ,511 , WINE_INI); + GetPrivateProfileString("spy", "Include", "INCLUDEALL",lpstrBuffer ,511 , WINE_INI); dprintf_message(stddeb,"SpyInit: Include=%s\n",lpstrBuffer); if( *lpstrBuffer != 0 ) if(strstr(lpstrBuffer,"INCLUDEALL")) diff --git a/misc/user.c b/misc/user.c index 1005ffd154e..27bd40c544f 100644 --- a/misc/user.c +++ b/misc/user.c @@ -73,6 +73,26 @@ BOOL SystemHeapInfo( SYSHEAPINFO *pHeapInfo ) } +/*********************************************************************** + * TimerCount (TOOLHELP.80) + */ +BOOL TimerCount( TIMERINFO *pTimerInfo ) +{ + /* FIXME + * In standard mode, dwmsSinceStart = dwmsThisVM + * + * I tested this, under Windows in enhanced mode, and + * if you never switch VM (ie start/stop DOS) these + * values should be the same as well. + * + * Also, Wine should adjust for the hardware timer + * to reduce the amount of error to ~1ms. + * I can't be bothered, can you? + */ + pTimerInfo->dwmsSinceStart = pTimerInfo->dwmsThisVM = GetTickCount(); + return TRUE; +} + /*********************************************************************** * USER_HeapInit */ diff --git a/misc/user32.c b/misc/user32.c index 5deaa83f07a..5097b8c231b 100644 --- a/misc/user32.c +++ b/misc/user32.c @@ -13,6 +13,7 @@ #include "relay32.h" #include "alias.h" #include "stackframe.h" +#include "xmalloc.h" /* Structure copy functions */ static void MSG16to32(MSG *msg16,struct WIN32_MSG *msg32) @@ -43,7 +44,11 @@ static void MSG32to16(struct WIN32_MSG *msg32,MSG *msg16) ATOM USER32_RegisterClassA(WNDCLASSA* wndclass) { WNDCLASS copy; - char *s1,*s2; + HANDLE classh = 0, menuh = 0; + SEGPTR classsegp, menusegp; + char *classbuf, *menubuf; + + ATOM retval; copy.style=wndclass->style; ALIAS_RegisterAlias(0,0,(DWORD)wndclass->lpfnWndProc); copy.lpfnWndProc=wndclass->lpfnWndProc; @@ -53,29 +58,31 @@ ATOM USER32_RegisterClassA(WNDCLASSA* wndclass) copy.hIcon=(HICON)wndclass->hIcon; copy.hCursor=(HCURSOR)wndclass->hCursor; copy.hbrBackground=(HBRUSH)wndclass->hbrBackground; + + /* FIXME: There has to be a better way of doing this - but neither + malloc nor alloca will work */ + if(wndclass->lpszMenuName) { - s1=alloca(strlen(wndclass->lpszMenuName)+1); - strcpy(s1,wndclass->lpszMenuName); - copy.lpszMenuName=MAKE_SEGPTR(s1); + menuh = GlobalAlloc(0, strlen(wndclass->lpszMenuName)+1); + menusegp = WIN16_GlobalLock(menuh); + menubuf = PTR_SEG_TO_LIN(menusegp); + strcpy( menubuf, wndclass->lpszMenuName); + copy.lpszMenuName=menusegp; }else copy.lpszMenuName=0; if(wndclass->lpszClassName) { - s2=alloca(strlen(wndclass->lpszClassName)+1); - strcpy(s2,wndclass->lpszClassName); - copy.lpszClassName=MAKE_SEGPTR(s2); + classh = GlobalAlloc(0, strlen(wndclass->lpszClassName)+1); + classsegp = WIN16_GlobalLock(classh); + classbuf = PTR_SEG_TO_LIN(classsegp); + strcpy( classbuf, wndclass->lpszClassName); + copy.lpszClassName=classsegp; } - return RegisterClass(©); -} - -/*********************************************************************** - * DefWindowProcA (USER32.125) - */ -LRESULT USER32_DefWindowProcA(DWORD hwnd,DWORD msg,DWORD wParam,DWORD lParam) -{ - /* some messages certainly need special casing. We come to that later */ - return DefWindowProc((HWND)hwnd,msg,wParam,lParam); + retval = RegisterClass(©); + GlobalFree(menuh); + GlobalFree(classh); + return retval; } /*********************************************************************** @@ -140,6 +147,16 @@ LONG USER32_DispatchMessageA(struct WIN32_MSG* lpmsg) return ret; } +/*********************************************************************** + * TranslateMessage (USER32.555) + */ +BOOL USER32_TranslateMessage(struct WIN32_MSG* lpmsg) +{ + MSG msg; + MSG32to16(lpmsg,&msg); + return TranslateMessage(&msg); +} + /*********************************************************************** * CreateWindowExA (USER32.82) */ @@ -147,16 +164,34 @@ DWORD USER32_CreateWindowExA(long flags,char* class,char *title, long style,int x,int y,int width,int height,DWORD parent,DWORD menu, DWORD instance,DWORD param) { + DWORD retval; + HANDLE classh, titleh; + SEGPTR classsegp, titlesegp; char *classbuf, *titlebuf; + /*Have to translate CW_USEDEFAULT */ if(x==0x80000000)x=CW_USEDEFAULT; + if(y==0x80000000)y=CW_USEDEFAULT; if(width==0x80000000)width=CW_USEDEFAULT; - classbuf = alloca( strlen(class)+1 ); + if(height==0x80000000)height=CW_USEDEFAULT; + + /* FIXME: There has to be a better way of doing this - but neither + malloc nor alloca will work */ + + classh = GlobalAlloc(0, strlen(class)+1); + titleh = GlobalAlloc(0, strlen(title)+1); + classsegp = WIN16_GlobalLock(classh); + titlesegp = WIN16_GlobalLock(titleh); + classbuf = PTR_SEG_TO_LIN(classsegp); + titlebuf = PTR_SEG_TO_LIN(titlesegp); strcpy( classbuf, class ); - titlebuf = alloca( strlen(title)+1 ); strcpy( titlebuf, title ); - return (DWORD) CreateWindowEx(flags,MAKE_SEGPTR(classbuf), - MAKE_SEGPTR(titlebuf),style,x,y,width,height, + + retval = (DWORD) CreateWindowEx(flags,classsegp, + titlesegp,style,x,y,width,height, (HWND)parent,(HMENU)menu,(HINSTANCE)instance, (LPVOID)param); + GlobalFree(classh); + GlobalFree(titleh); + return retval; } diff --git a/misc/winsocket.c b/misc/winsocket.c index 536e5db2b49..0586e5260d7 100644 --- a/misc/winsocket.c +++ b/misc/winsocket.c @@ -23,7 +23,7 @@ #include #include #include -#undef TRANSPARENT + #include "winsock.h" #include "toolhelp.h" #include "stddebug.h" @@ -35,9 +35,7 @@ static key_t wine_key = 0; static FARPROC BlockFunction; static fd_set fd_in_use; -#ifdef __FreeBSD__ extern int h_errno; -#endif /* __FreeBSD__ */ struct ipc_packet { long mtype; @@ -660,11 +658,10 @@ SOCKET WINSOCK_socket(INT af, INT type, INT protocol) } if (sock > 0xffff) { - /* we set the value of wsa_errno directly, because - * only support socket numbers up to 0xffff. The - * value return indicates there are no descriptors available + /* we only support socket numbers up to 0xffff. The return + * value indicates there are no more descriptors available */ - wsa_errno = WSAEMFILE; + WSASetLastError(WSAEMFILE); return INVALID_SOCKET; } @@ -846,7 +843,7 @@ static void recv_message(int sig) if (!message_is_valid) { if (msgrcv(wine_key, (struct msgbuf*)&(message), IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1) { - perror("wine: msgrcv"); + perror("wine: winsock: msgrcv"); break; } } @@ -877,7 +874,7 @@ static void send_message( HWND hWnd, u_int wMsg, HANDLE handle, long lParam) if (msgsnd(wine_key, (struct msgbuf*)&(message), IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1) - perror("wine: msgsnd"); + perror("wine: winsock: msgsnd"); kill(getppid(), SIGUSR1); } @@ -1046,42 +1043,44 @@ HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent) { - long event; - fd_set read_fds, write_fds, except_fds; + long event; + fd_set read_fds, write_fds, except_fds; + int errors = 0; - dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent); + dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND "NPFMT", wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent); - /* remove outstanding asyncselect() processes */ - /* kill */ + /* remove outstanding asyncselect() processes */ + /* kill */ - if (wMsg == 0 && lEvent == 0) - return 0; + if (wMsg == 0 && lEvent == 0) + return 0; - if (fork()) { - return 0; - } else { - while (1) { - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - FD_ZERO(&except_fds); + if (fork()) { + return 0; + } else { + while (1) { + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + FD_ZERO(&except_fds); - if (lEvent & FD_READ) - FD_SET(s, &read_fds); - if (lEvent & FD_WRITE) - FD_SET(s, &write_fds); + if (lEvent & FD_READ) + FD_SET(s, &read_fds); + if (lEvent & FD_WRITE) + FD_SET(s, &write_fds); - fcntl(s, F_SETFL, O_NONBLOCK); - select(s + 1, &read_fds, &write_fds, &except_fds, NULL); + fcntl(s, F_SETFL, O_NONBLOCK); + if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) { + errors = wsaerrno(); + } - event = 0; - if (FD_ISSET(s, &read_fds)) - event |= FD_READ; - if (FD_ISSET(s, &write_fds)) - event |= FD_WRITE; - /* FIXME: the first time through we get a winsock error of 2, why? */ - send_message(hWnd, wMsg, (HANDLE)s, (wsaerrno() << 16) | event); - } - } + event = 0; + if (FD_ISSET(s, &read_fds)) + event |= FD_READ; + if (FD_ISSET(s, &write_fds)) + event |= FD_WRITE; + send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors)); + } + } } INT WSAFDIsSet(INT fd, fd_set *set) @@ -1183,7 +1182,7 @@ INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) /* ipc stuff */ if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1) - perror("wine: msgget"); + perror("wine: winsock: msgget"); signal(SIGUSR1, recv_message); @@ -1201,7 +1200,7 @@ INT WSACleanup(void) if (wine_key) if (msgctl(wine_key, IPC_RMID, NULL) == -1) - perror("wine: shmctl"); + perror("wine: winsock: shmctl"); for (fd = 0; fd != FD_SETSIZE; fd++) if (FD_ISSET(fd, &fd_in_use)) diff --git a/misc/xmalloc.c b/misc/xmalloc.c index 24dcef58794..58b9681359d 100644 --- a/misc/xmalloc.c +++ b/misc/xmalloc.c @@ -14,6 +14,7 @@ */ #include +#include #include "xmalloc.h" void * @@ -42,3 +43,15 @@ xrealloc (void *ptr, size_t size) } return res; } + + +char *xstrdup( const char *str ) +{ + char *res = strdup( str ); + if (!res) + { + fprintf (stderr, "Virtual memory exhausted.\n"); + exit (1); + } + return res; +} diff --git a/miscemu/cpu.c b/miscemu/cpu.c index 436c35b44e9..bde9e366c64 100644 --- a/miscemu/cpu.c +++ b/miscemu/cpu.c @@ -23,7 +23,7 @@ int runtime_cpu (void) { char info[5], value[5]; while (fscanf (f, " %4s%*s : %4s%*s", info, value) == 2) - if (!strcasecmp (info, "cpu")) + if (!lstrcmpi (info, "cpu")) { if (isdigit (value[0]) && value[1] == '8' && value[2] == '6' && value[3] == 0) diff --git a/miscemu/dpmi.c b/miscemu/dpmi.c index 1ba8f1a42ba..760be10304d 100644 --- a/miscemu/dpmi.c +++ b/miscemu/dpmi.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include "windows.h" @@ -240,6 +241,11 @@ void INT_Int31Handler( struct sigcontext_struct context ) case 0x0601: /* Unlock linear region */ break; /* Just ignore it */ + case 0x0604: /* Get page size */ + BX_reg(&context) = 0; + CX_reg(&context) = 4096; + break; + default: INT_BARF( &context, 0x31 ); AX_reg(&context) = 0x8001; /* unsupported function */ diff --git a/miscemu/instr.c b/miscemu/instr.c index 8b795a960cf..14ac461321e 100644 --- a/miscemu/instr.c +++ b/miscemu/instr.c @@ -426,8 +426,7 @@ BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context ) (long_addr ? ECX_reg(context) : CX_reg(context)) : 1; int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1; int step = (EFL_reg(context) & 0x400) ? -opsize : +opsize; - int seg = outp ? (segprefix >= 0 ? segprefix : DS_reg(context)) - : ES_reg(context); /* FIXME: is this right? */ + int seg = outp ? DS_reg(context) : ES_reg(context); /* FIXME: is this right? */ if (outp) /* FIXME: Check segment readable. */ diff --git a/miscemu/int21.c b/miscemu/int21.c index 143e04aba0f..16b5f8f9864 100644 --- a/miscemu/int21.c +++ b/miscemu/int21.c @@ -16,6 +16,8 @@ #include #include #include "dos_fs.h" +#include "drive.h" +#include "file.h" #include "windows.h" #include "msdos.h" #include "registers.h" @@ -23,6 +25,7 @@ #include "task.h" #include "options.h" #include "miscemu.h" +#include "xmalloc.h" #include "stddebug.h" #include "debug.h" #ifdef __svr4__ @@ -31,6 +34,10 @@ #define LOCK_SH 1 #define LOCK_NB 8 #endif + + +#define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive()) + /* Define the drive parameter block, as used by int21/1F * and int21/32. This table can be accessed through the * global 'dpb' pointer, which points into the local dos @@ -78,7 +85,7 @@ extern char TempDirectory[]; static int Error(int e, int class, int el) { - return DOS_Error(e,class,el); + return DOS_ERROR( e, class, SA_Abort, el ); } @@ -135,53 +142,48 @@ static void CreateBPB(int drive, BYTE *data) static void GetFreeDiskSpace(struct sigcontext_struct *context) { - int drive; - long size,available; + long size,available; + int drive = DOS_GET_DRIVE( DL_reg(context) ); - if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive(); - else drive = DL_reg(context) - 1; + if (!DRIVE_IsValid(drive)) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(context) = 0xffff; + return; + } - if (!DOS_ValidDrive(drive)) { - Error(InvalidDrive, EC_MediaError , EL_Disk); - AX_reg(context) = 0xffff; - return; - } - - if (!DOS_GetFreeSpace(drive, &size, &available)) { - Error(GeneralFailure, EC_MediaError , EL_Disk); - AX_reg(context) = 0xffff; - return; - } + if (!DOS_GetFreeSpace(drive, &size, &available)) { + DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(context) = 0xffff; + return; + } - AX_reg(context) = (drive < 2) ? 1 : 64; /* 64 for hard-disks, 1 for diskettes */ - CX_reg(context) = 512; - - BX_reg(context) = (available / (CX_reg(context) * AX_reg(context))); - DX_reg(context) = (size / (CX_reg(context) * AX_reg(context))); - Error (0,0,0); + AX_reg(context) = (drive < 2) ? 1 : 64; /* 64 for hard-disks, 1 for diskettes */ + CX_reg(context) = 512; + BX_reg(context) = (available / (CX_reg(context) * AX_reg(context))); + DX_reg(context) = (size / (CX_reg(context) * AX_reg(context))); + Error (0,0,0); } static void GetDriveAllocInfo(struct sigcontext_struct *context) { - int drive; - long size, available; + long size, available; + int drive = DOS_GET_DRIVE( DL_reg(context) ); - if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive(); - else drive = DL_reg(context) - 1; + if (!DRIVE_IsValid(drive)) + { + AX_reg(context) = 4; + CX_reg(context) = 512; + DX_reg(context) = 0; + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + return; + } - if (!DOS_ValidDrive(drive)) + if (!DOS_GetFreeSpace(drive, &size, &available)) { - AX_reg(context) = 4; - CX_reg(context) = 512; - DX_reg(context) = 0; - Error (InvalidDrive, EC_MediaError, EL_Disk); - return; - } - - if (!DOS_GetFreeSpace(drive, &size, &available)) { - Error(GeneralFailure, EC_MediaError , EL_Disk); - AX_reg(context) = 0xffff; - return; + DOS_ERROR( ER_GeneralFailure, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(context) = 0xffff; + return; } AX_reg(context) = (drive < 2) ? 1 : 64; /* 64 for hard-disks, 1 for diskettes */ @@ -197,10 +199,10 @@ static void GetDriveAllocInfo(struct sigcontext_struct *context) static void GetDrivePB(struct sigcontext_struct *context, int drive) { - if(!DOS_ValidDrive(drive)) + if(!DRIVE_IsValid(drive)) { - Error (InvalidDrive, EC_MediaError, EL_Disk); - AX_reg(context) = 0x00ff; + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(context) = 0x00ff; } else { @@ -237,116 +239,6 @@ static void GetDrivePB(struct sigcontext_struct *context, int drive) } } -static void ReadFile(struct sigcontext_struct *context) -{ - char *ptr; - int size; - - /* can't read from stdout / stderr */ - if ((BX_reg(context) == 1) || (BX_reg(context) == 2)) { - Error (InvalidHandle, EL_Unknown, EC_Unknown); - AX_reg(context) = InvalidHandle; - SET_CFLAG(context); - dprintf_int(stddeb, "int21: read (%d, void *, 0x%x) = EBADF\n", - BX_reg(context), CX_reg(context)); - return; - } - - ptr = PTR_SEG_OFF_TO_LIN (DS_reg(context),DX_reg(context)); - if (BX_reg(context) == 0) { - *ptr = EOF; - Error (0,0,0); - AX_reg(context) = 1; - RESET_CFLAG(context); - dprintf_int(stddeb, "int21: read (%d, void *, 0x%x) = EOF\n", - BX_reg(context), CX_reg(context)); - return; - } else { - size = read(BX_reg(context), ptr, CX_reg(context)); - dprintf_int(stddeb,"int21: read(%d, %04x:%04x, 0x%x) = 0x%x\n", - BX_reg(context), DS_reg(context), DX_reg(context), - CX_reg(context), size ); - if (size == -1) { - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; - } - Error (0,0,0); - AX_reg(context) = size; - RESET_CFLAG(context); - } -} - -static void WriteFile(struct sigcontext_struct *context) -{ - char *ptr; - int x,size; - - ptr = PTR_SEG_OFF_TO_LIN (DS_reg(context),DX_reg(context)); - - if (BX_reg(context) == 0) { - Error (InvalidHandle, EC_Unknown, EL_Unknown); - EAX_reg(context) = InvalidHandle; - SET_CFLAG(context); - return; - } - - if (BX_reg(context) < 3) { - for (x = 0;x != CX_reg(context);x++) { - dprintf_int(stddeb, "%c", *ptr++); - } - fflush(stddeb); - - Error (0,0,0); - AX_reg(context) = CX_reg(context); - RESET_CFLAG(context); - } else { - /* well, this function already handles everything we need */ - size = _lwrite(BX_reg(context),ptr,CX_reg(context)); - if (size == -1) { /* HFILE_ERROR == -1 */ - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; - } - Error (0,0,0); - AX_reg(context) = size; - RESET_CFLAG(context); - } -} - -static void SeekFile(struct sigcontext_struct *context) -{ - off_t status, fileoffset; - - switch (AL_reg(context)) - { - case 1: fileoffset = SEEK_CUR; - break; - case 2: fileoffset = SEEK_END; - break; - default: - case 0: fileoffset = SEEK_SET; - break; - } - status = lseek(BX_reg(context), (CX_reg(context) << 16) + DX_reg(context), fileoffset); - - dprintf_int (stddeb, "int21: seek (%d, 0x%x, %d) = 0x%lx\n", - BX_reg(context), (CX_reg(context) << 16) + DX_reg(context), AL_reg(context), status); - - if (status == -1) - { - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; - } - Error (0,0,0); - AX_reg(context) = LOWORD(status); - DX_reg(context) = HIWORD(status); - RESET_CFLAG(context); -} static void ioctlGetDeviceInfo(struct sigcontext_struct *context) { @@ -357,6 +249,8 @@ static void ioctlGetDeviceInfo(struct sigcontext_struct *context) { case 0: case 1: + DX_reg(context) = 2; /* FIXME */ + break; case 2: DX_reg(context) = 0x80d0 | (1 << (BX_reg(context) != 0)); RESET_CFLAG(context); @@ -387,17 +281,14 @@ static void ioctlGetDeviceInfo(struct sigcontext_struct *context) static void ioctlGenericBlkDevReq(struct sigcontext_struct *context) { BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); - int drive; + int drive = DOS_GET_DRIVE( BL_reg(context) ); - if (BL_reg(context) == 0) drive = DOS_GetDefaultDrive(); - else drive = BL_reg(context) - 1; - - if (!DOS_ValidDrive(drive)) + if (!DRIVE_IsValid(drive)) { - Error( FileNotFound, EC_NotFound, EL_Disk ); - AX_reg(context) = FileNotFound; - SET_CFLAG(context); - return; + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + AX_reg(context) = DOS_ExtendedError; + SET_CFLAG(context); + return; } if (CH_reg(context) != 0x08) @@ -459,68 +350,32 @@ static void INT21_GetSystemTime(struct sigcontext_struct *context) /* Note hundredths of seconds */ } -static void GetExtendedErrorInfo(struct sigcontext_struct *context) -{ - AX_reg(context) = ExtendedError; - BX_reg(context) = (ErrorClass << 8) | Action; - CH_reg(context) = ErrorLocus; -} - static void CreateFile(struct sigcontext_struct *context) { - int handle; - handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context), - DX_reg(context))), - O_CREAT | O_TRUNC | O_RDWR, 0666 ); - if (handle == -1) { - errno_to_doserr(); - AX_reg(context) = ExtendedError; + AX_reg(context) = _lcreat( PTR_SEG_OFF_TO_LIN( DS_reg(context), + DX_reg(context) ), CX_reg(context) ); + if (AX_reg(context) == (WORD)HFILE_ERROR) + { + AX_reg(context) = DOS_ExtendedError; SET_CFLAG(context); - return; } - Error (0,0,0); - AX_reg(context) = handle; - RESET_CFLAG(context); } + void OpenExistingFile(struct sigcontext_struct *context) { + AX_reg(context) = _lopen( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), + AL_reg(context) ); + if (AX_reg(context) == (WORD)HFILE_ERROR) + { + AX_reg(context) = DOS_ExtendedError; + SET_CFLAG(context); + } +#if 0 int handle; int mode; int lock; - switch (AX_reg(context) & 0x0007) - { - case 0: - mode = O_RDONLY; - break; - - case 1: - mode = O_WRONLY; - break; - - default: - mode = O_RDWR; - break; - } - - if ((handle = open(DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context))), - mode)) == -1) - { - if( Options.allowReadOnly ) - handle = open( DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context))), - O_RDONLY ); - if( handle == -1 ) - { - dprintf_int (stddeb, "int21: open (%s, %d) = -1\n", - DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context))), mode); - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; - } - } - dprintf_int (stddeb, "int21: open (%s, %d) = %d\n", DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context))), mode, handle); @@ -585,28 +440,22 @@ void OpenExistingFile(struct sigcontext_struct *context) Error (0,0,0); AX_reg(context) = handle; RESET_CFLAG(context); +#endif } static void CloseFile(struct sigcontext_struct *context) { - dprintf_int (stddeb, "int21: close (%d)\n", BX_reg(context)); - - if (_lclose( BX_reg(context) )) - { - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; - } - Error (0,0,0); - AX_reg(context) = NoError; - RESET_CFLAG(context); + if ((AX_reg(context) = _lclose( BX_reg(context) )) != 0) + { + AX_reg(context) = DOS_ExtendedError; + SET_CFLAG(context); + } } void ExtendedOpenCreateFile(struct sigcontext_struct *context) { dprintf_int(stddeb, "int21: extended open/create: file= %s \n", - DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)))); + DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE)); /* Shuffle arguments to call OpenExistingFile */ AL_reg(context) = BL_reg(context); DX_reg(context) = SI_reg(context); @@ -615,7 +464,7 @@ void ExtendedOpenCreateFile(struct sigcontext_struct *context) if ((EFL_reg(context) & 0x0001)==0) { /* It exists */ dprintf_int(stddeb, "int21: extended open/create %s exists \n", - DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)))); + DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),TRUE)); /* Now decide what do do */ if ((DL_reg(context) & 0x0007)== 0) { @@ -668,7 +517,7 @@ void ExtendedOpenCreateFile(struct sigcontext_struct *context) else /* file does not exist */ { dprintf_int(stddeb, "int21: extended open/create %s dosen't exists \n", - DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)))); + DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE)); if ((DL_reg(context) & 0x00F0)== 0) { CX_reg(context) = 0; SET_CFLAG(context); @@ -689,318 +538,222 @@ void ExtendedOpenCreateFile(struct sigcontext_struct *context) return; } } -static void RenameFile(struct sigcontext_struct *context) -{ - char *newname, *oldname; - /* FIXME: should not rename over an existing file */ - dprintf_int(stddeb,"int21: renaming %s to %s\n", - (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), - (char *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context))); + +static int INT21_RenameFile(struct sigcontext_struct *context) +{ + const char *newname, *oldname; + char *buffer; + + /* FIXME: should not rename over an existing file */ + dprintf_int(stddeb,"int21: renaming %s to %s\n", + (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), + (char *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context))); - oldname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context), - DX_reg(context)) ); - newname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(ES_reg(context), - DI_reg(context)) ); - - rename( oldname, newname); - RESET_CFLAG(context); + oldname = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context), + DX_reg(context)), TRUE ); + if (!oldname) return 0; + buffer = xstrdup( oldname ); + newname = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(ES_reg(context), + DI_reg(context)), FALSE ); + if (!newname) + { + free( buffer ); + return 0; + } + + if (rename( buffer, newname) == -1) + { + FILE_SetDosError(); + free( buffer ); + return 0; + } + free( buffer ); + return 1; } -static void MakeDir(struct sigcontext_struct *context) +static void INT21_ChangeDir(struct sigcontext_struct *context) { - char *dirname; + int drive; + char *dirname = PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)); - dprintf_int(stddeb,"int21: makedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) ); + dprintf_int(stddeb,"int21: changedir %s\n", dirname); + if (dirname[1] == ':') + { + drive = toupper(dirname[0]) - 'A'; + dirname += 2; + } + else drive = DRIVE_GetCurrentDrive(); + if (!DRIVE_Chdir( drive, dirname )) + { + AX_reg(context) = DOS_ExtendedError; + SET_CFLAG(context); + } +} + + +static int INT21_FindFirst(struct sigcontext_struct *context) +{ + const char *path, *unixPath, *mask; + char *p; + FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(); + + path = (const char *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); + dta->unixPath = NULL; + if (!(unixPath = DOSFS_GetUnixFileName( path, FALSE ))) + { + AX_reg(context) = DOS_ExtendedError; + SET_CFLAG(context); + return 0; + } + dta->unixPath = xstrdup( unixPath ); + p = strrchr( dta->unixPath, '/' ); + *p = '\0'; + if (!(mask = DOSFS_ToDosFCBFormat( p + 1 ))) + { + free( dta->unixPath ); + dta->unixPath = NULL; + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + AX_reg(context) = ER_FileNotFound; + SET_CFLAG(context); + return 0; + } + memcpy( dta->mask, mask, sizeof(dta->mask) ); + dta->drive = (path[1] == ':') ? toupper(path[0]) - 'A' + : DRIVE_GetCurrentDrive(); + dta->count = 0; + dta->search_attr = CL_reg(context); + return 1; +} + + +static int INT21_FindNext(struct sigcontext_struct *context) +{ + FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(); + DOS_DIRENT entry; + int count; + + if (!dta->unixPath) return 0; + if (!(count = DOSFS_FindNext( dta->unixPath, dta->mask, dta->drive, + dta->search_attr, dta->count, &entry ))) + { + free( dta->unixPath ); + dta->unixPath = NULL; + return 0; + } + if ((int)dta->count + count > 0xffff) + { + fprintf( stderr, "Too many directory entries in %s\n", dta->unixPath ); + free( dta->unixPath ); + dta->unixPath = NULL; + return 0; + } + dta->count += count; + dta->fileattr = entry.attr; + dta->filetime = entry.time; + dta->filedate = entry.date; + dta->filesize = entry.size; + strcpy( dta->filename, DOSFS_ToDosDTAFormat( entry.name ) ); + return 1; +} + + +static int INT21_SetFileDateTime(struct sigcontext_struct *context) +{ + fprintf( stderr, "INT21_SetFileDateTime: not implemented yet.\n" ); + return 1; +#if 0 + char *filename; + struct utimbuf filetime; - if ((dirname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context), - DX_reg(context)) ))== NULL) { - Error( CanNotMakeDir, EC_AccessDenied, EL_Disk ); - AX_reg(context) = CanNotMakeDir; - SET_CFLAG(context); - return; - } + /* FIXME: Argument isn't the name of the file in DS:DX, + but the file handle in BX */ + filename = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context), + DX_reg(context)),TRUE ); - if ((mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO) == -1) && errno!=EEXIST) { - Error( CanNotMakeDir, EC_AccessDenied, EL_Disk ); - AX_reg(context) = CanNotMakeDir; - SET_CFLAG(context); - return; - } - RESET_CFLAG(context); + filetime.actime = 0L; + filetime.modtime = filetime.actime; + + utime(filename, &filetime); + RESET_CFLAG(context); +#endif } -static void ChangeDir(struct sigcontext_struct *context) + +static int INT21_CreateTempFile(struct sigcontext_struct *context) { - int drive; - char *dirname = PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)); - drive = DOS_GetDefaultDrive(); - dprintf_int(stddeb,"int21: changedir %s\n", dirname); - if (dirname != NULL && dirname[1] == ':') { - drive = toupper(dirname[0]) - 'A'; - dirname += 2; - } - if (!DOS_ChangeDir(drive, dirname)) - { - SET_CFLAG(context); - AX_reg(context)=0x03; - } -} + static int counter = 0; + char *name = PTR_SEG_OFF_TO_LIN( DS_reg(context), DX_reg(context) ); + char *p = name + strlen(name); -static void RemoveDir(struct sigcontext_struct *context) -{ - char *dirname; - - dprintf_int(stddeb,"int21: removedir %s\n", (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) ); - - if ((dirname = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) ))== NULL) { - Error( PathNotFound, EC_NotFound, EL_Disk ); - AX_reg(context) = PathNotFound; - SET_CFLAG(context); - return; - } - -/* - if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) { - AL = CanNotRemoveCwd; - SET_CFLAG(context); - } -*/ - if (rmdir(dirname) == -1) { - Error( AccessDenied, EC_AccessDenied, EL_Disk ); - AX_reg(context) = AccessDenied; - SET_CFLAG(context); - return; - } - RESET_CFLAG(context); -} - -static void FindNext(struct sigcontext_struct *context) -{ - struct dosdirent *dp; - struct tm *t; - BYTE *dta = GetCurrentDTA(); - - memcpy(&dp, dta+0x11, sizeof(dp)); - - dprintf_int(stddeb, "int21: FindNext, dta %p, dp %p\n", dta, dp); - do { - if ((dp = DOS_readdir(dp)) == NULL) { - Error(NoMoreFiles, EC_MediaError , EL_Disk); - AX_reg(context) = NoMoreFiles; - SET_CFLAG(context); - return; - } - } /* while (*(dta + 0x0c) != dp->attribute);*/ - while ( ( dp->search_attribute & dp->attribute) != dp->attribute); - - *(dta + 0x15) = dp->attribute; - setword(&dta[0x0d], dp->entnum); - - t = localtime(&(dp->filetime)); - setword(&dta[0x16], (t->tm_hour << 11) + (t->tm_min << 5) + - (t->tm_sec / 2)); /* time */ - setword(&dta[0x18], ((t->tm_year - 80) << 9) + (t->tm_mon << 5) + - (t->tm_mday)); /* date */ - setdword(&dta[0x1a], dp->filesize); - strncpy(dta + 0x1e, dp->filename, 12); - *(dta + 0x1e + 13) = 0; - AnsiUpper(dta+0x1e); - - AX_reg(context) = 0; - RESET_CFLAG(context); - - dprintf_int(stddeb, "int21: FindNext -- (%s) index=%d size=%ld\n", dp->filename, dp->entnum, dp->filesize); -} - -static void FindFirst(struct sigcontext_struct *context) -{ - BYTE drive, *path = PTR_SEG_OFF_TO_LIN(DS_reg(context), - DX_reg(context)); - struct dosdirent *dp; - - BYTE *dta = GetCurrentDTA(); - - dprintf_int(stddeb, "int21: FindFirst path = %s\n", path); - - if ((*path)&&(path[1] == ':')) { - drive = (islower(*path) ? toupper(*path) : *path) - 'A'; - - if (!DOS_ValidDrive(drive)) { - Error(InvalidDrive, EC_MediaError , EL_Disk); - AX_reg(context) = InvalidDrive; - SET_CFLAG(context); - return; - } - } else - drive = DOS_GetDefaultDrive(); - - *dta = drive; - memset(dta + 1 , '?', 11); - *(dta + 0x0c) = ECX_reg(context) & (FA_LABEL | FA_DIREC); - - if ((dp = DOS_opendir(path)) == NULL) { - Error(PathNotFound, EC_MediaError, EL_Disk); - AX_reg(context) = FileNotFound; - SET_CFLAG(context); - return; - } - - dp->search_attribute = ECX_reg(context) & (FA_LABEL | FA_DIREC); - memcpy(dta + 0x11, &dp, sizeof(dp)); - FindNext(context); - -} - -static void GetFileDateTime(struct sigcontext_struct *context) -{ - struct stat filestat; - struct tm *now; - - fstat( BX_reg(context), &filestat ); - now = localtime (&filestat.st_mtime); - - CX_reg(context) = ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2); - DX_reg(context) = (((now->tm_year + 1900 - 1980) * 0x200) + - (now->tm_mon * 0x20) + now->tm_mday); - - RESET_CFLAG(context); -} - -static void SetFileDateTime(struct sigcontext_struct *context) -{ - char *filename; - struct utimbuf filetime; - - /* FIXME: Argument isn't the name of the file in DS:DX, - but the file handle in BX */ - filename = DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context), - DX_reg(context)) ); - - filetime.actime = 0L; - filetime.modtime = filetime.actime; - - utime(filename, &filetime); - RESET_CFLAG(context); -} - -static void CreateTempFile(struct sigcontext_struct *context) -{ - char temp[256]; - int handle; - static int counter = 0; - - sprintf(temp,"%s\\win%d.%03d",TempDirectory,(int) getpid(), counter); + for (;;) + { + sprintf( p, "wine%04x.%03d", (int)getpid(), counter ); counter = (counter + 1) % 1000; - dprintf_int(stddeb,"CreateTempFile %s\n",temp); - - handle = open(DOS_GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR, 0666); - - if (handle == -1) { - Error( WriteProtected, EC_AccessDenied, EL_Disk ); - AX_reg(context) = WriteProtected; - SET_CFLAG(context); - return; - } - - strcpy(PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), temp); - - AX_reg(context) = handle; - RESET_CFLAG(context); -} - -static void CreateNewFile(struct sigcontext_struct *context) -{ - int handle; - - if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)) ), - O_CREAT | O_EXCL | O_RDWR, 0666)) == -1) + if ((AX_reg(context) = _lcreat_uniq( name, 0 )) != (WORD)HFILE_ERROR) { - Error( WriteProtected, EC_AccessDenied, EL_Disk ); - AX_reg(context) = WriteProtected; - SET_CFLAG(context); - return; - } - - AX_reg(context) = handle; - RESET_CFLAG(context); + dprintf_int( stddeb, "INT21_CreateTempFile: created %s\n", name ); + return 1; + } + if (DOS_ExtendedError != ER_FileExists) return 0; + } } -static void GetCurrentDirectory(struct sigcontext_struct *context) + +static int INT21_GetCurrentDirectory(struct sigcontext_struct *context) { - int drive; + int drive = DOS_GET_DRIVE( DL_reg(context) ); + char *ptr = (char *)PTR_SEG_OFF_TO_LIN( DS_reg(context), SI_reg(context) ); - if (DL_reg(context) == 0) drive = DOS_GetDefaultDrive(); - else drive = DL_reg(context) - 1; + if (!DRIVE_IsValid(drive)) + { + DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk ); + return 0; + } - if (!DOS_ValidDrive(drive)) - { - Error( InvalidDrive, EC_NotFound, EL_Disk ); - AX_reg(context) = InvalidDrive; - SET_CFLAG(context); - return; - } - - strcpy(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)), - DOS_GetCurrentDir(drive) ); - RESET_CFLAG(context); + lstrcpyn( ptr, DRIVE_GetDosCwd(drive), 64 ); + if (!ptr[0]) strcpy( ptr, "\\" ); + return 1; } -static void GetDiskSerialNumber(struct sigcontext_struct *context) + +static int INT21_GetDiskSerialNumber(struct sigcontext_struct *context) { - int drive; - BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); - DWORD serialnumber; + BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); + int drive = DOS_GET_DRIVE( BL_reg(context) ); - if (BL_reg(context) == 0) drive = DOS_GetDefaultDrive(); - else drive = BL_reg(context) - 1; - - if (!DOS_ValidDrive(drive)) - { - Error( InvalidDrive, EC_NotFound, EL_Disk ); - AX_reg(context) = InvalidDrive; - SET_CFLAG(context); - return; - } - - DOS_GetSerialNumber(drive, &serialnumber); - - setword(dataptr, 0); - setdword(&dataptr[2], serialnumber); - strncpy(dataptr + 6, DOS_GetVolumeLabel(drive), 8); - strncpy(dataptr + 0x11, "FAT16 ", 8); - - AX_reg(context) = 0; - RESET_CFLAG(context); + if (!DRIVE_IsValid(drive)) + { + DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk ); + return 0; + } + + *(WORD *)dataptr = 0; + *(DWORD *)(dataptr + 2) = DRIVE_GetSerialNumber( drive ); + memcpy( dataptr + 6, DRIVE_GetLabel( drive ), 11 ); + strncpy(dataptr + 0x11, "FAT16 ", 8); + return 1; } -static void SetDiskSerialNumber(struct sigcontext_struct *context) + +static int INT21_SetDiskSerialNumber(struct sigcontext_struct *context) { - int drive; - BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); - DWORD serialnumber; + BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); + int drive = DOS_GET_DRIVE( BL_reg(context) ); - if (BL_reg(context) == 0) drive = DOS_GetDefaultDrive(); - else drive = BL_reg(context) - 1; + if (!DRIVE_IsValid(drive)) + { + DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk ); + return 0; + } - if (!DOS_ValidDrive(drive)) - { - Error( InvalidDrive, EC_NotFound, EL_Disk ); - AX_reg(context) = InvalidDrive; - SET_CFLAG(context); - return; - } - - serialnumber = dataptr[1] + (dataptr[2] << 8) + (dataptr[3] << 16) + - (dataptr[4] << 24); - - DOS_SetSerialNumber(drive, serialnumber); - AX_reg(context) = 1; - RESET_CFLAG(context); + DRIVE_SetSerialNumber( drive, *(DWORD *)(dataptr + 2) ); + return 1; } + static void DumpFCB(BYTE *fcb) { int x, y; @@ -1044,15 +797,15 @@ static void FindFirstFCB(struct sigcontext_struct *context) if (standard_fcb->drive) { drive = standard_fcb->drive - 1; - if (!DOS_ValidDrive(drive)) + if (!DRIVE_IsValid(drive)) { - Error (InvalidDrive, EC_MediaError, EL_Disk); - AX_reg(context) = 0xff; - return; + DOS_ERROR(ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk); + AX_reg(context) = 0xff; + return; } } else - drive = DOS_GetDefaultDrive(); + drive = DRIVE_GetCurrentDrive(); output_fcb->drive = drive; @@ -1062,19 +815,17 @@ static void FindFirstFCB(struct sigcontext_struct *context) { *(dta+6) = FA_LABEL; memset(&output_fcb->name, ' ', 11); - if (DOS_GetVolumeLabel(drive) != NULL) - { - strncpy(output_fcb->name, DOS_GetVolumeLabel(drive), 11); - AX_reg(context) = 0x00; - return; - } + memcpy(output_fcb->name, DRIVE_GetLabel(drive), 11); + AX_reg(context) = 0x00; + return; } } strncpy(output_fcb->name, standard_fcb->name, 11); if (*fcb == 0xff) - *(dta+6) = ( *(fcb+6) & (!FA_DIREC)); + *(dta+6) = ( *(fcb+6) & (!FA_DIRECTORY)); +#if 0 sprintf(path,"%c:*.*",drive+'A'); if ((output_fcb->directory = DOS_opendir(path))==NULL) { @@ -1082,25 +833,23 @@ static void FindFirstFCB(struct sigcontext_struct *context) AX_reg(context) = 0xff; return; } - +#endif } static void DeleteFileFCB(struct sigcontext_struct *context) { + fprintf( stderr, "DeleteFileFCB: not implemented yet\n" ); +#if 0 BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); - int drive; struct dosdirent *dp; char temp[256], *ptr; + int drive = DOS_GET_DRIVE( *fcb ); DumpFCB( fcb ); - if (*fcb) - drive = *fcb - 1; - else - drive = DOS_GetDefaultDrive(); - - strcpy(temp, DOS_GetCurrentDir(drive)); + temp[0] = '\\'; + strcpy(temp+1, DRIVE_GetDosCwd(drive)); strcat(temp, "\\"); strncat(temp, fcb + 1, 8); ChopOffWhiteSpace(temp); @@ -1113,7 +862,8 @@ static void DeleteFileFCB(struct sigcontext_struct *context) return; } - strcpy(temp, DOS_GetCurrentDir(drive) ); + temp[0] = '\\'; + strcpy(temp+1, DRIVE_GetDosCwd(drive) ); strcat(temp, "\\"); ptr = temp + strlen(temp); @@ -1126,23 +876,22 @@ static void DeleteFileFCB(struct sigcontext_struct *context) } DOS_closedir(dp); AX_reg(context) = 0; +#endif } static void RenameFileFCB(struct sigcontext_struct *context) { + fprintf( stderr, "RenameFileFCB: not implemented yet\n" ); +#if 0 BYTE *fcb = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context)); - int drive; struct dosdirent *dp; char temp[256], oldname[256], newname[256], *oldnameptr, *newnameptr; + int drive = DOS_GET_DRIVE( *fcb ); DumpFCB( fcb ); - if (*fcb) - drive = *fcb - 1; - else - drive = DOS_GetDefaultDrive(); - - strcpy(temp, DOS_GetCurrentDir(drive)); + temp[0] = '\\'; + strcpy(temp+1, DRIVE_GetDosCwd(drive) ); strcat(temp, "\\"); strncat(temp, fcb + 1, 8); ChopOffWhiteSpace(temp); @@ -1155,12 +904,11 @@ static void RenameFileFCB(struct sigcontext_struct *context) return; } - strcpy(oldname, DOS_GetCurrentDir(drive) ); + oldname[0] = '\\'; + strcpy(oldname+1, DRIVE_GetDosCwd(drive) ); strcat(oldname, "\\"); + strcpy( newname, oldname ); oldnameptr = oldname + strlen(oldname); - - strcpy(newname, DOS_GetCurrentDir(drive) ); - strcat(newname, "\\"); newnameptr = newname + strlen(newname); while (DOS_readdir(dp) != NULL) @@ -1172,12 +920,14 @@ static void RenameFileFCB(struct sigcontext_struct *context) } DOS_closedir(dp); AX_reg(context) = 0; +#endif } static void fLock (struct sigcontext_struct * context) { +#if 0 struct flock f; int result,retries=sharing_retries; @@ -1217,43 +967,26 @@ static void fLock (struct sigcontext_struct * context) if(result) { - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; + FILE_SetDosError(); + AX_reg(context) = DOS_ExtendedError; + SET_CFLAG(context); + return; } - - Error (0,0,0); - RESET_CFLAG(context); +#endif } -static void GetFileAttribute (struct sigcontext_struct * context) +static int INT21_GetFileAttribute (struct sigcontext_struct * context) { - char *filename = PTR_SEG_OFF_TO_LIN (DS_reg(context),DX_reg(context)); - struct stat s; - int res; + const char *unixName; - res = stat(DOS_GetUnixFileName(filename), &s); - if (res==-1) - { - errno_to_doserr(); - AX_reg(context) = ExtendedError; - SET_CFLAG(context); - return; - } - - CX_reg(context) = 0; - if (S_ISDIR(s.st_mode)) - CX_reg(context) |= 0x10; - if ((S_IWRITE & s.st_mode) != S_IWRITE) - CX_reg(context) |= 0x01; - - dprintf_int (stddeb, "int21: GetFileAttributes (%s) = 0x%x\n", - filename, CX_reg(context) ); - - RESET_CFLAG(context); - Error (0,0,0); + unixName = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), TRUE ); + if (!unixName) return 0; + if (!FILE_Stat( unixName, &CL_reg(context), NULL, NULL, NULL )) return 0; + CH_reg(context) = 0; + dprintf_int( stddeb, "INT21_GetFileAttributes(%s) = 0x%x\n", + unixName, CX_reg(context) ); + return 1; } @@ -1264,176 +997,173 @@ extern void LOCAL_PrintHeap (WORD ds); */ void DOS3Call( struct sigcontext_struct context ) { - int drive; + dprintf_int( stddeb, "int21: AX=%04x BX=%04x CX=%04x DX=%04x " + "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n", + AX_reg(&context), BX_reg(&context), CX_reg(&context), + DX_reg(&context), SI_reg(&context), DI_reg(&context), + DS_reg(&context), ES_reg(&context), EFL_reg(&context)); - if (AH_reg(&context) == 0x59) + if (AH_reg(&context) == 0x59) /* Get extended error info */ { - GetExtendedErrorInfo(&context); - return; - } - else + AX_reg(&context) = DOS_ExtendedError; + BH_reg(&context) = DOS_ErrorClass; + BL_reg(&context) = DOS_ErrorAction; + CH_reg(&context) = DOS_ErrorLocus; + return; + } + + DOS_ERROR( 0, 0, 0, 0 ); + RESET_CFLAG(&context); /* Not sure if this is a good idea */ + + switch(AH_reg(&context)) { - Error (0,0,0); - switch(AH_reg(&context)) - { - case 0x00: /* TERMINATE PROGRAM */ - TASK_KillCurrentTask( 0 ); - break; + case 0x00: /* TERMINATE PROGRAM */ + TASK_KillCurrentTask( 0 ); + break; - case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */ - case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */ - case 0x03: /* READ CHARACTER FROM STDAUX */ - case 0x04: /* WRITE CHARACTER TO STDAUX */ - case 0x05: /* WRITE CHARACTER TO PRINTER */ - case 0x06: /* DIRECT CONSOLE IN/OUTPUT */ - case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */ - case 0x08: /* CHARACTER INPUT WITHOUT ECHO */ - case 0x09: /* WRITE STRING TO STANDARD OUTPUT */ - case 0x0a: /* BUFFERED INPUT */ - case 0x0b: /* GET STDIN STATUS */ - case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */ - case 0x0f: /* OPEN FILE USING FCB */ - case 0x10: /* CLOSE FILE USING FCB */ - case 0x12: /* FIND NEXT MATCHING FILE USING FCB */ - case 0x14: /* SEQUENTIAL READ FROM FCB FILE */ - case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */ - case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */ - case 0x21: /* READ RANDOM RECORD FROM FCB FILE */ - case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */ - case 0x23: /* GET FILE SIZE FOR FCB */ - case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */ - case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */ - case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */ - case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */ - case 0x29: /* PARSE FILENAME INTO FCB */ - case 0x2e: /* SET VERIFY FLAG */ - INT_BARF( &context, 0x21 ); - break; + case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */ + case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */ + case 0x03: /* READ CHARACTER FROM STDAUX */ + case 0x04: /* WRITE CHARACTER TO STDAUX */ + case 0x05: /* WRITE CHARACTER TO PRINTER */ + case 0x06: /* DIRECT CONSOLE IN/OUTPUT */ + case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */ + case 0x08: /* CHARACTER INPUT WITHOUT ECHO */ + case 0x09: /* WRITE STRING TO STANDARD OUTPUT */ + case 0x0a: /* BUFFERED INPUT */ + case 0x0b: /* GET STDIN STATUS */ + case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */ + case 0x0f: /* OPEN FILE USING FCB */ + case 0x10: /* CLOSE FILE USING FCB */ + case 0x12: /* FIND NEXT MATCHING FILE USING FCB */ + case 0x14: /* SEQUENTIAL READ FROM FCB FILE */ + case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */ + case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */ + case 0x21: /* READ RANDOM RECORD FROM FCB FILE */ + case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */ + case 0x23: /* GET FILE SIZE FOR FCB */ + case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */ + case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */ + case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */ + case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */ + case 0x29: /* PARSE FILENAME INTO FCB */ + case 0x2e: /* SET VERIFY FLAG */ + case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER + "SWITCHAR" - SET SWITCH CHARACTER + "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */ + case 0x54: /* GET VERIFY FLAG */ + INT_BARF( &context, 0x21 ); + break; - case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER - "SWITCHAR" - SET SWITCH CHARACTER - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */ - case 0x54: /* GET VERIFY FLAG */ - INT_BARF( &context, 0x21 ); - break; - - case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */ - case 0x1d: - case 0x1e: - case 0x20: - case 0x6b: /* NULL FUNCTION */ - AL_reg(&context) = 0; - break; + case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */ + case 0x1d: + case 0x1e: + case 0x20: + case 0x6b: /* NULL FUNCTION */ + AL_reg(&context) = 0; + break; - case 0x5c: /* "FLOCK" - RECORD LOCKING */ - fLock(&context); - break; + case 0x5c: /* "FLOCK" - RECORD LOCKING */ + fLock(&context); + break; - case 0x0d: /* DISK BUFFER FLUSH */ - RESET_CFLAG(&context); /* dos 6+ only */ - break; + case 0x0d: /* DISK BUFFER FLUSH */ + RESET_CFLAG(&context); /* dos 6+ only */ + break; - case 0x0e: /* SELECT DEFAULT DRIVE */ - if (!DOS_ValidDrive(DL_reg(&context))) - Error (InvalidDrive, EC_MediaError, EL_Disk); - else - { - DOS_SetDefaultDrive(DL_reg(&context)); - Error(0,0,0); - } - AL_reg(&context) = MAX_DOS_DRIVES; - break; + case 0x0e: /* SELECT DEFAULT DRIVE */ + DRIVE_SetCurrentDrive( DL_reg(&context) ); + AL_reg(&context) = MAX_DOS_DRIVES; + break; - case 0x11: /* FIND FIRST MATCHING FILE USING FCB */ - FindFirstFCB(&context); - break; + case 0x11: /* FIND FIRST MATCHING FILE USING FCB */ + FindFirstFCB(&context); + break; - case 0x13: /* DELETE FILE USING FCB */ - DeleteFileFCB(&context); - break; + case 0x13: /* DELETE FILE USING FCB */ + DeleteFileFCB(&context); + break; - case 0x17: /* RENAME FILE USING FCB */ - RenameFileFCB(&context); - break; + case 0x17: /* RENAME FILE USING FCB */ + RenameFileFCB(&context); + break; - case 0x19: /* GET CURRENT DEFAULT DRIVE */ - AL_reg(&context) = DOS_GetDefaultDrive(); - Error (0,0,0); - break; + case 0x19: /* GET CURRENT DEFAULT DRIVE */ + AL_reg(&context) = DRIVE_GetCurrentDrive(); + break; - case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */ - { - TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); - pTask->dta = MAKELONG( DX_reg(&context), DS_reg(&context) ); - dprintf_int(stddeb, "int21: Set DTA: %08lx\n", pTask->dta); - } - break; + case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */ + { + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + pTask->dta = MAKELONG( DX_reg(&context), DS_reg(&context) ); + dprintf_int(stddeb, "int21: Set DTA: %08lx\n", pTask->dta); + } + break; - case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */ - DL_reg(&context) = 0; - GetDriveAllocInfo(&context); - break; + case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */ + DL_reg(&context) = 0; + GetDriveAllocInfo(&context); + break; - case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */ - GetDriveAllocInfo(&context); - break; + case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */ + GetDriveAllocInfo(&context); + break; - case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */ - GetDrivePB(&context, DOS_GetDefaultDrive()); - break; + case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */ + GetDrivePB(&context, DRIVE_GetCurrentDrive()); + break; - case 0x25: /* SET INTERRUPT VECTOR */ - INT_SetHandler( AL_reg(&context), - MAKELONG( DX_reg(&context), DS_reg(&context) ) ); - break; + case 0x25: /* SET INTERRUPT VECTOR */ + INT_SetHandler( AL_reg(&context), + MAKELONG( DX_reg(&context), DS_reg(&context) ) ); + break; - case 0x2a: /* GET SYSTEM DATE */ - GetSystemDate(&context); - break; + case 0x2a: /* GET SYSTEM DATE */ + GetSystemDate(&context); + break; - case 0x2b: /* SET SYSTEM DATE */ - fprintf( stdnimp, "SetSystemDate(%02d/%02d/%04d): not allowed\n", - DL_reg(&context), DH_reg(&context), CX_reg(&context) ); - AL_reg(&context) = 0; /* Let's pretend we succeeded */ - break; + case 0x2b: /* SET SYSTEM DATE */ + fprintf( stdnimp, "SetSystemDate(%02d/%02d/%04d): not allowed\n", + DL_reg(&context), DH_reg(&context), CX_reg(&context) ); + AL_reg(&context) = 0; /* Let's pretend we succeeded */ + break; - case 0x2c: /* GET SYSTEM TIME */ - INT21_GetSystemTime(&context); - break; + case 0x2c: /* GET SYSTEM TIME */ + INT21_GetSystemTime(&context); + break; - case 0x2d: /* SET SYSTEM TIME */ - fprintf( stdnimp, "SetSystemTime(%02d:%02d:%02d.%02d): not allowed\n", - CH_reg(&context), CL_reg(&context), - DH_reg(&context), DL_reg(&context) ); - AL_reg(&context) = 0; /* Let's pretend we succeeded */ - break; + case 0x2d: /* SET SYSTEM TIME */ + fprintf( stdnimp, "SetSystemTime(%02d:%02d:%02d.%02d): not allowed\n", + CH_reg(&context), CL_reg(&context), + DH_reg(&context), DL_reg(&context) ); + AL_reg(&context) = 0; /* Let's pretend we succeeded */ + break; - case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */ - { - TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); - ES_reg(&context) = SELECTOROF( pTask->dta ); - BX_reg(&context) = OFFSETOF( pTask->dta ); - } - break; + case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */ + { + TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() ); + ES_reg(&context) = SELECTOROF( pTask->dta ); + BX_reg(&context) = OFFSETOF( pTask->dta ); + } + break; - case 0x30: /* GET DOS VERSION */ - AX_reg(&context) = DOSVERSION; - BX_reg(&context) = 0x0012; /* 0x123456 is Wine's serial # */ - CX_reg(&context) = 0x3456; - break; + case 0x30: /* GET DOS VERSION */ + AX_reg(&context) = DOSVERSION; + BX_reg(&context) = 0x0012; /* 0x123456 is Wine's serial # */ + CX_reg(&context) = 0x3456; + break; - case 0x31: /* TERMINATE AND STAY RESIDENT */ - INT_BARF( &context, 0x21 ); - break; + case 0x31: /* TERMINATE AND STAY RESIDENT */ + INT_BARF( &context, 0x21 ); + break; - case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */ - GetDrivePB(&context, (DL_reg(&context) == 0) ? - (DOS_GetDefaultDrive()) : (DL_reg(&context)-1)); - break; + case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */ + GetDrivePB(&context, DOS_GET_DRIVE( DL_reg(&context) ) ); + break; - case 0x33: /* MULTIPLEXED */ - switch (AL_reg(&context)) - { + case 0x33: /* MULTIPLEXED */ + switch (AL_reg(&context)) + { case 0x00: /* GET CURRENT EXTENDED BREAK STATE */ DL_reg(&context) = 0; break; @@ -1458,403 +1188,495 @@ void DOS3Call( struct sigcontext_struct context ) default: INT_BARF( &context, 0x21 ); break; - } - break; + } + break; - case 0x34: /* GET ADDRESS OF INDOS FLAG */ - ES_reg(&context) = DosHeapHandle; - BX_reg(&context) = (int)&heap->InDosFlag - (int)heap; - break; + case 0x34: /* GET ADDRESS OF INDOS FLAG */ + ES_reg(&context) = DosHeapHandle; + BX_reg(&context) = (int)&heap->InDosFlag - (int)heap; + break; - case 0x35: /* GET INTERRUPT VECTOR */ + case 0x35: /* GET INTERRUPT VECTOR */ + { + SEGPTR addr = INT_GetHandler( AL_reg(&context) ); + ES_reg(&context) = SELECTOROF(addr); + BX_reg(&context) = OFFSETOF(addr); + } + break; + + case 0x36: /* GET FREE DISK SPACE */ + GetFreeDiskSpace(&context); + break; + + case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */ + AX_reg(&context) = 0x02; /* no country support available */ + SET_CFLAG(&context); + break; + + case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */ + if (!FILE_MakeDir( PTR_SEG_OFF_TO_LIN( DS_reg(&context), + DX_reg(&context) ))) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */ + if (!FILE_RemoveDir( PTR_SEG_OFF_TO_LIN( DS_reg(&context), + DX_reg(&context) ))) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */ + INT21_ChangeDir(&context); + break; + + case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */ + AX_reg(&context) = _lcreat( PTR_SEG_OFF_TO_LIN( DS_reg(&context), + DX_reg(&context) ), CX_reg(&context) ); + if (AX_reg(&context) == (WORD)HFILE_ERROR) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x3d: /* "OPEN" - OPEN EXISTING FILE */ + OpenExistingFile(&context); + break; + + case 0x3e: /* "CLOSE" - CLOSE FILE */ + if ((AX_reg(&context) = _lclose( BX_reg(&context) )) != 0) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */ + if ((AX_reg(&context) = _lread( BX_reg(&context), + PTR_SEG_OFF_TO_LIN( DS_reg(&context),DX_reg(&context) ), + CX_reg(&context))) == (WORD)HFILE_ERROR) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */ + if ((AX_reg(&context) = _lwrite( BX_reg(&context), + PTR_SEG_OFF_TO_LIN( DS_reg(&context),DX_reg(&context) ), + CX_reg(&context))) == (WORD)HFILE_ERROR) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x41: /* "UNLINK" - DELETE FILE */ + if (!FILE_Unlink( PTR_SEG_OFF_TO_LIN( DS_reg(&context), + DX_reg(&context) ))) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */ + { + LONG status = _llseek( BX_reg(&context), + MAKELONG(DX_reg(&context),CX_reg(&context)), + AL_reg(&context) ); + if (status == HFILE_ERROR) { - SEGPTR addr = INT_GetHandler( AL_reg(&context) ); - ES_reg(&context) = SELECTOROF(addr); - BX_reg(&context) = OFFSETOF(addr); - } - break; - - case 0x36: /* GET FREE DISK SPACE */ - GetFreeDiskSpace(&context); - break; - - case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */ - AX_reg(&context) = 0x02; /* no country support available */ - SET_CFLAG(&context); - break; - - case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */ - MakeDir(&context); - break; - - case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */ - RemoveDir(&context); - break; - - case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */ - ChangeDir(&context); - break; - - case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */ - CreateFile(&context); - break; - - case 0x3d: /* "OPEN" - OPEN EXISTING FILE */ - OpenExistingFile(&context); - break; - - case 0x3e: /* "CLOSE" - CLOSE FILE */ - CloseFile(&context); - break; - - case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */ - ReadFile(&context); - break; - - case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */ - WriteFile(&context); - break; - - case 0x41: /* "UNLINK" - DELETE FILE */ - if (unlink( DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(&context),DX_reg(&context))) ) == -1) { - errno_to_doserr(); - AX_reg(&context) = ExtendedError; - SET_CFLAG(&context); - break; - } - Error(0,0,0); - RESET_CFLAG(&context); - break; - - case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */ - SeekFile(&context); - break; - - case 0x43: /* FILE ATTRIBUTES */ - switch (AL_reg(&context)) - { - case 0x00: - GetFileAttribute(&context); - break; - case 0x01: - RESET_CFLAG(&context); - break; - } - break; - - case 0x44: /* IOCTL */ - switch (AL_reg(&context)) - { - case 0x00: - ioctlGetDeviceInfo(&context); - break; - - case 0x01: - - break; - case 0x08: /* Check if drive is removable. */ - drive = BL_reg(&context) ? (BL_reg(&context) - 1) - : DOS_GetDefaultDrive(); - if(!DOS_ValidDrive(drive)) - { - Error( InvalidDrive, EC_NotFound, EL_Disk ); - AX_reg(&context) = InvalidDrive; - SET_CFLAG(&context); - } - else - { - if (drive > 1) - AX_reg(&context) = 1; /* not removable */ - else - AX_reg(&context) = 0; /* removable */ - RESET_CFLAG(&context); - } - break; - - case 0x09: /* CHECK IF BLOCK DEVICE REMOTE */ - drive = BL_reg(&context) ? (BL_reg(&context) - 1) - : DOS_GetDefaultDrive(); - if(!DOS_ValidDrive(drive)) - { - Error( InvalidDrive, EC_NotFound, EL_Disk ); - AX_reg(&context) = InvalidDrive; - SET_CFLAG(&context); - } - else - { - DX_reg(&context) = (1<<9) | (1<<12) | (1<<15); - RESET_CFLAG(&context); - } - break; - case 0x0a: /* check if handle (BX) is remote */ - /* returns DX, bit 15 set if remote, bit 14 set if date/time - * not set on close - */ - DX_reg(&context) = 0; - RESET_CFLAG(&context); - break; - case 0x0b: /* SET SHARING RETRY COUNT */ - if (!CX_reg(&context)) - { - AX_reg(&context) = 1; - SET_CFLAG(&context); - break; - } - sharing_pause = CX_reg(&context); - if (!DX_reg(&context)) - sharing_retries = DX_reg(&context); - RESET_CFLAG(&context); - break; - - case 0x0d: - ioctlGenericBlkDevReq(&context); - break; - - case 0x0F: /* Set logical drive mapping */ - /* FIXME: Not implemented at the moment, always returns error - */ - fprintf(stdnimp,"Attempt to map drive %02x\n",BL_reg(&context)); - AX_reg(&context) = 0x0001; /* invalid function */ + AX_reg(&context) = DOS_ExtendedError; SET_CFLAG(&context); break; + } + AX_reg(&context) = LOWORD(status); + DX_reg(&context) = HIWORD(status); + } + break; + + case 0x43: /* FILE ATTRIBUTES */ + switch (AL_reg(&context)) + { + case 0x00: + if (!INT21_GetFileAttribute(&context)) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + case 0x01: + RESET_CFLAG(&context); + break; + } + break; + + case 0x44: /* IOCTL */ + switch (AL_reg(&context)) + { + case 0x00: + ioctlGetDeviceInfo(&context); + break; + + case 0x01: + break; + + case 0x08: /* Check if drive is removable. */ + switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) ))) + { + case DRIVE_CANNOTDETERMINE: + DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk ); + AX_reg(&context) = ER_InvalidDrive; + SET_CFLAG(&context); + break; + case DRIVE_REMOVABLE: + AX_reg(&context) = 0; /* removable */ + break; + default: + AX_reg(&context) = 1; /* not removable */ + break; + } + break; + + case 0x09: /* CHECK IF BLOCK DEVICE REMOTE */ + switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) ))) + { + case DRIVE_CANNOTDETERMINE: + DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk ); + AX_reg(&context) = ER_InvalidDrive; + SET_CFLAG(&context); + break; + case DRIVE_REMOTE: + DX_reg(&context) = (1<<9) | (1<<12); /* remote */ + break; + default: + DX_reg(&context) = 0; /* FIXME: use driver attr here */ + break; + } + break; + + case 0x0a: /* check if handle (BX) is remote */ + /* returns DX, bit 15 set if remote, bit 14 set if date/time + * not set on close + */ + DX_reg(&context) = 0; + break; + + case 0x0b: /* SET SHARING RETRY COUNT */ + if (!CX_reg(&context)) + { + AX_reg(&context) = 1; + SET_CFLAG(&context); + break; + } + sharing_pause = CX_reg(&context); + if (!DX_reg(&context)) + sharing_retries = DX_reg(&context); + RESET_CFLAG(&context); + break; + + case 0x0d: + ioctlGenericBlkDevReq(&context); + break; + + case 0x0F: /* Set logical drive mapping */ + /* FIXME: Not implemented at the moment, always returns error + */ + INT_BARF( &context, 0x21 ); + AX_reg(&context) = 0x0001; /* invalid function */ + SET_CFLAG(&context); + break; - default: - INT_BARF( &context, 0x21 ); - break; - } - break; + default: + INT_BARF( &context, 0x21 ); + break; + } + break; - case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */ - if ((AX_reg(&context) = dup(BX_reg(&context))) == 0xffff) + case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */ + if ((AX_reg(&context) = FILE_Dup(BX_reg(&context))) == (WORD)HFILE_ERROR) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */ + if (FILE_Dup2( BX_reg(&context), CX_reg(&context) ) == HFILE_ERROR) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x47: /* "CWD" - GET CURRENT DIRECTORY */ + if (!INT21_GetCurrentDirectory(&context)) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + else AX_reg(&context) = 0x0100; + /* intlist: many Microsoft products for Windows rely on this */ + break; + + case 0x48: /* ALLOCATE MEMORY */ + case 0x49: /* FREE MEMORY */ + case 0x4a: /* RESIZE MEMORY BLOCK */ + INT_BARF( &context, 0x21 ); + break; + + case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */ + WinExec( PTR_SEG_OFF_TO_LIN( DS_reg(&context), DX_reg(&context) ), + SW_NORMAL ); + break; + + case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */ + TASK_KillCurrentTask( AL_reg(&context) ); + break; + + case 0x4d: /* GET RETURN CODE */ + AX_reg(&context) = 0; /* normal exit */ + break; + + case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */ + if (!INT21_FindFirst(&context)) break; + /* fall through */ + + case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */ + if (!INT21_FindNext(&context)) + { + DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(&context) = ER_NoMoreFiles; + SET_CFLAG(&context); + } + break; + + case 0x51: /* GET PSP ADDRESS */ + case 0x62: /* GET PSP ADDRESS */ + /* FIXME: should we return the original DOS PSP upon */ + /* Windows startup ? */ + BX_reg(&context) = GetCurrentPDB(); + break; + + case 0x52: /* "SYSVARS" - GET LIST OF LISTS */ + ES_reg(&context) = 0x0; + BX_reg(&context) = 0x0; + INT_BARF( &context, 0x21 ); + break; + + case 0x56: /* "RENAME" - RENAME FILE */ + if (!INT21_RenameFile(&context)) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x57: /* FILE DATE AND TIME */ + switch (AL_reg(&context)) + { + case 0x00: + if (!FILE_Fstat( BX_reg(&context), NULL, NULL, + &DX_reg(&context), &CX_reg(&context) )) { - errno_to_doserr(); - AX_reg(&context) = ExtendedError; + AX_reg(&context) = DOS_ExtendedError; SET_CFLAG(&context); } - else RESET_CFLAG(&context); - break; - - case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */ - if (dup2( BX_reg(&context), CX_reg(&context) ) == -1) + break; + case 0x01: + if (!INT21_SetFileDateTime(&context)) { - errno_to_doserr(); - AX_reg(&context) = ExtendedError; + AX_reg(&context) = DOS_ExtendedError; SET_CFLAG(&context); } - else RESET_CFLAG(&context); break; + } + break; - case 0x47: /* "CWD" - GET CURRENT DIRECTORY */ - GetCurrentDirectory(&context); - AX_reg(&context) = 0x0100; - /* intlist: many Microsoft products for Windows rely on this */ - break; - - case 0x48: /* ALLOCATE MEMORY */ - case 0x49: /* FREE MEMORY */ - case 0x4a: /* RESIZE MEMORY BLOCK */ - INT_BARF( &context, 0x21 ); + case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */ + switch (AL_reg(&context)) + { + case 0x00: + AX_reg(&context) = 1; break; - - case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */ - WinExec( PTR_SEG_OFF_TO_LIN(DS_reg(&context),DX_reg(&context)), - SW_NORMAL ); - break; - - case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */ - TASK_KillCurrentTask( AL_reg(&context) ); - break; - - case 0x4d: /* GET RETURN CODE */ - AX_reg(&context) = NoError; /* normal exit */ - break; - - case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */ - FindFirst(&context); - break; - - case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */ - FindNext(&context); - break; - - case 0x51: /* GET PSP ADDRESS */ - case 0x62: /* GET PSP ADDRESS */ - /* FIXME: should we return the original DOS PSP upon */ - /* Windows startup ? */ - BX_reg(&context) = GetCurrentPDB(); - break; - - case 0x52: /* "SYSVARS" - GET LIST OF LISTS */ - ES_reg(&context) = 0x0; - BX_reg(&context) = 0x0; - INT_BARF( &context, 0x21 ); + case 0x02: + AX_reg(&context) = 0; break; - - case 0x56: /* "RENAME" - RENAME FILE */ - RenameFile(&context); - break; - - case 0x57: /* FILE DATE AND TIME */ - switch (AL_reg(&context)) - { - case 0x00: - GetFileDateTime(&context); - break; - case 0x01: - SetFileDateTime(&context); - break; - } - break; - - case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */ - switch (AL_reg(&context)) - { - case 0x00: - AX_reg(&context) = 1; - break; - case 0x02: - AX_reg(&context) = 0; - break; - case 0x01: - case 0x03: - break; - } - RESET_CFLAG(&context); - break; - - case 0x5a: /* CREATE TEMPORARY FILE */ - CreateTempFile(&context); - break; - - case 0x5b: /* CREATE NEW FILE */ - CreateNewFile(&context); - break; - - case 0x5d: /* NETWORK */ - case 0x5e: - /* network software not installed */ - AX_reg(&context) = NoNetwork; - SET_CFLAG(&context); - break; - - case 0x5f: /* NETWORK */ - switch (AL_reg(&context)) - { - case 0x07: /* ENABLE DRIVE */ - if (!DOS_EnableDrive(DL_reg(&context))) - { - Error(InvalidDrive, EC_MediaError , EL_Disk); - AX_reg(&context) = InvalidDrive; - SET_CFLAG(&context); - break; - } - else - { - RESET_CFLAG(&context); - break; - } - case 0x08: /* DISABLE DRIVE */ - if (!DOS_DisableDrive(DL_reg(&context))) - { - Error(InvalidDrive, EC_MediaError , EL_Disk); - AX_reg(&context) = InvalidDrive; - SET_CFLAG(&context); - break; - } - else - { - RESET_CFLAG(&context); - break; - } - default: - /* network software not installed */ - AX_reg(&context) = NoNetwork; - SET_CFLAG(&context); - break; - } - break; - - case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ - strncpy(PTR_SEG_OFF_TO_LIN(ES_reg(&context),DI_reg(&context)), - PTR_SEG_OFF_TO_LIN(DS_reg(&context),SI_reg(&context)), - strlen(PTR_SEG_OFF_TO_LIN(DS_reg(&context),SI_reg(&context))) & 0x7f); - RESET_CFLAG(&context); - break; - - case 0x61: /* UNUSED */ - case 0x63: /* UNUSED */ - case 0x64: /* OS/2 DOS BOX */ - case 0x65: /* GET EXTENDED COUNTRY INFORMATION */ - INT_BARF( &context, 0x21 ); + case 0x01: + case 0x03: break; - - case 0x66: /* GLOBAL CODE PAGE TABLE */ - switch (AL_reg(&context)) + } + RESET_CFLAG(&context); + break; + + case 0x5a: /* CREATE TEMPORARY FILE */ + if (!INT21_CreateTempFile(&context)) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x5b: /* CREATE NEW FILE */ + if ((AX_reg(&context) = _lcreat_uniq( PTR_SEG_OFF_TO_LIN(DS_reg(&context),DX_reg(&context)), 0 )) == (WORD)HFILE_ERROR) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x5d: /* NETWORK */ + case 0x5e: + /* network software not installed */ + DOS_ERROR( ER_NoNetwork, EC_NotFound, SA_Abort, EL_Network ); + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + break; + + case 0x5f: /* NETWORK */ + switch (AL_reg(&context)) + { + case 0x07: /* ENABLE DRIVE */ + if (!DRIVE_Enable( DL_reg(&context) )) { - case 0x01: - DX_reg(&context) = BX_reg(&context) = CodePage; - RESET_CFLAG(&context); - break; - case 0x02: - CodePage = BX_reg(&context); - RESET_CFLAG(&context); - break; - } - break; + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; - case 0x67: /* SET HANDLE COUNT */ - RESET_CFLAG(&context); - break; + case 0x08: /* DISABLE DRIVE */ + if (!DRIVE_Disable( DL_reg(&context) )) + { + DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; - case 0x68: /* "FFLUSH" - COMMIT FILE */ - case 0x6a: /* COMMIT FILE */ - fsync( BX_reg(&context) ); - RESET_CFLAG(&context); - break; + default: + /* network software not installed */ + DOS_ERROR( ER_NoNetwork, EC_NotFound, SA_Abort, EL_Network ); + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + break; + } + break; + + case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ + { + const char *truename = DOSFS_GetDosTrueName( PTR_SEG_OFF_TO_LIN(DS_reg(&context),SI_reg(&context) ), FALSE ); + if (!truename) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + else + { + lstrcpyn(PTR_SEG_OFF_TO_LIN(ES_reg(&context),DI_reg(&context)), + truename, 128 ); + AX_reg(&context) = 0; + } + } + break; + + case 0x61: /* UNUSED */ + case 0x63: /* UNUSED */ + case 0x64: /* OS/2 DOS BOX */ + case 0x65: /* GET EXTENDED COUNTRY INFORMATION */ + INT_BARF( &context, 0x21 ); + break; - case 0x69: /* DISK SERIAL NUMBER */ - switch (AL_reg(&context)) - { - case 0x00: - GetDiskSerialNumber(&context); - break; - case 0x01: - SetDiskSerialNumber(&context); - break; - } - break; + case 0x66: /* GLOBAL CODE PAGE TABLE */ + switch (AL_reg(&context)) + { + case 0x01: + DX_reg(&context) = BX_reg(&context) = CodePage; + RESET_CFLAG(&context); + break; + case 0x02: + CodePage = BX_reg(&context); + RESET_CFLAG(&context); + break; + } + break; + + case 0x67: /* SET HANDLE COUNT */ + SetHandleCount( BX_reg(&context) ); + if (DOS_ExtendedError) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x68: /* "FFLUSH" - COMMIT FILE */ + case 0x6a: /* COMMIT FILE */ + if (fsync( FILE_GetUnixHandle( BX_reg(&context) )) == -1) + { + FILE_SetDosError(); + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + break; + + case 0x69: /* DISK SERIAL NUMBER */ + switch (AL_reg(&context)) + { + case 0x00: + if (!INT21_GetDiskSerialNumber(&context)) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + else AX_reg(&context) = 0; + break; + case 0x01: + if (!INT21_SetDiskSerialNumber(&context)) + { + AX_reg(&context) = DOS_ExtendedError; + SET_CFLAG(&context); + } + else AX_reg(&context) = 1; + break; + } + break; - case 0x6C: /* Extended Open/Create*/ - ExtendedOpenCreateFile(&context); - break; + case 0x6C: /* Extended Open/Create*/ + ExtendedOpenCreateFile(&context); + break; - case 0x70: /* MS-DOS 7 (Windows95) - ??? (country-specific?)*/ - case 0x71: /* MS-DOS 7 (Chicago) - LONG FILENAME FUNCTIONS */ - case 0x72: /* MS-DOS 7 (Windows95) - ??? */ - case 0x73: /* MS-DOS 7 (Windows95) - DRIVE LOCKING ??? */ - dprintf_int(stddeb,"int21: windows95 function AX %04x\n", - AX_reg(&context)); - dprintf_int(stddeb, " returning unimplemented\n"); - SET_CFLAG(&context); - AL_reg(&context) = 0; - break; + case 0x70: /* MS-DOS 7 (Windows95) - ??? (country-specific?)*/ + case 0x71: /* MS-DOS 7 (Chicago) - LONG FILENAME FUNCTIONS */ + case 0x72: /* MS-DOS 7 (Windows95) - ??? */ + case 0x73: /* MS-DOS 7 (Windows95) - DRIVE LOCKING ??? */ + dprintf_int(stddeb,"int21: windows95 function AX %04x\n", + AX_reg(&context)); + dprintf_int(stddeb, " returning unimplemented\n"); + SET_CFLAG(&context); + AL_reg(&context) = 0; + break; - case 0xdc: /* CONNECTION SERVICES - GET CONNECTION NUMBER */ - break; + case 0xdc: /* CONNECTION SERVICES - GET CONNECTION NUMBER */ + case 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */ + break; - case 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */ - break; - - default: - INT_BARF( &context, 0x21 ); - break; - } + default: + INT_BARF( &context, 0x21 ); + break; } - dprintf_int(stddeb,"ret21: AX %04x, BX %04x, CX %04x, DX %04x, " - "SI %04x, DI %04x, DS %04x, ES %04x EFL %08lx\n", - AX_reg(&context), BX_reg(&context), CX_reg(&context), - DX_reg(&context), SI_reg(&context), DI_reg(&context), - DS_reg(&context), ES_reg(&context), EFL_reg(&context)); + dprintf_int( stddeb, "ret21: AX=%04x BX=%04x CX=%04x DX=%04x " + "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n", + AX_reg(&context), BX_reg(&context), CX_reg(&context), + DX_reg(&context), SI_reg(&context), DI_reg(&context), + DS_reg(&context), ES_reg(&context), EFL_reg(&context)); } diff --git a/miscemu/int25.c b/miscemu/int25.c index 58b3858db2c..799816aa02a 100644 --- a/miscemu/int25.c +++ b/miscemu/int25.c @@ -6,7 +6,7 @@ #include "ldt.h" #include "wine.h" #include "miscemu.h" -#include "dos_fs.h" +#include "drive.h" #include "stddebug.h" /* #define DEBUG_INT */ #include "debug.h" @@ -21,7 +21,7 @@ void INT_Int25Handler( struct sigcontext_struct context ) BYTE *dataptr = PTR_SEG_OFF_TO_LIN( DS_reg(&context), BX_reg(&context) ); DWORD begin, length; - if (!DOS_ValidDrive(AL_reg(&context))) + if (!DRIVE_IsValid(AL_reg(&context))) { SET_CFLAG(&context); AX_reg(&context) = 0x0101; /* unknown unit */ @@ -30,9 +30,9 @@ void INT_Int25Handler( struct sigcontext_struct context ) if (CX_reg(&context) == 0xffff) { - begin = getdword(dataptr); - length = getword(&dataptr[4]); - dataptr = (BYTE *) PTR_SEG_TO_LIN(getdword(&dataptr[6])); + begin = *(DWORD *)dataptr; + length = *(WORD *)(dataptr + 4); + dataptr = (BYTE *)PTR_SEG_TO_LIN( *(SEGPTR *)(dataptr + 6) ); } else { diff --git a/miscemu/int26.c b/miscemu/int26.c index 06f70ed68f5..53f1abc4bbb 100644 --- a/miscemu/int26.c +++ b/miscemu/int26.c @@ -5,7 +5,7 @@ #include "ldt.h" #include "wine.h" #include "miscemu.h" -#include "dos_fs.h" +#include "drive.h" #include "stddebug.h" /* #define DEBUG_INT */ #include "debug.h" @@ -20,7 +20,7 @@ void INT_Int26Handler( struct sigcontext_struct context ) BYTE *dataptr = PTR_SEG_OFF_TO_LIN( DS_reg(&context), BX_reg(&context) ); DWORD begin, length; - if (!DOS_ValidDrive(AL_reg(&context))) + if (!DRIVE_IsValid(AL_reg(&context))) { SET_CFLAG(&context); AX_reg(&context) = 0x0101; /* unknown unit */ @@ -29,9 +29,9 @@ void INT_Int26Handler( struct sigcontext_struct context ) if (CX_reg(&context) == 0xffff) { - begin = getdword(dataptr); - length = getword(&dataptr[4]); - dataptr = (BYTE *) PTR_SEG_TO_LIN(getdword(&dataptr[6])); + begin = *(DWORD *)dataptr; + length = *(WORD *)(dataptr + 4); + dataptr = (BYTE *)PTR_SEG_TO_LIN( *(SEGPTR *)(dataptr + 6) ); } else { diff --git a/miscemu/interrupts.c b/miscemu/interrupts.c index a9b8b8abdcd..97a94908fcc 100644 --- a/miscemu/interrupts.c +++ b/miscemu/interrupts.c @@ -5,8 +5,9 @@ */ #include "windows.h" +#include "drive.h" #include "miscemu.h" -#include "dos_fs.h" +#include "msdos.h" #include "module.h" #include "registers.h" #include "stackframe.h" @@ -81,7 +82,55 @@ void INT_DummyHandler( struct sigcontext_struct context ) */ void INT_Int11Handler( struct sigcontext_struct context ) { - AX_reg(&context) = DOS_GetEquipment(); + int diskdrives = 0; + int parallelports = 0; + int serialports = 0; + int x; + +/* borrowed from Ralph Brown's interrupt lists + + bits 15-14: number of parallel devices + bit 13: [Conv] Internal modem + bit 12: reserved + bits 11- 9: number of serial devices + bit 8: reserved + bits 7- 6: number of diskette drives minus one + bits 5- 4: Initial video mode: + 00b = EGA,VGA,PGA + 01b = 40 x 25 color + 10b = 80 x 25 color + 11b = 80 x 25 mono + bit 3: reserved + bit 2: [PS] =1 if pointing device + [non-PS] reserved + bit 1: =1 if math co-processor + bit 0: =1 if diskette available for boot +*/ +/* Currently the only of these bits correctly set are: + bits 15-14 } Added by William Owen Smith, + bits 11-9 } wos@dcs.warwick.ac.uk + bits 7-6 + bit 2 (always set) +*/ + + if (DRIVE_IsValid(0)) diskdrives++; + if (DRIVE_IsValid(1)) diskdrives++; + if (diskdrives) diskdrives--; + + for (x=0; x!=MAX_PORTS; x++) + { + if (COM[x].devicename) + serialports++; + if (LPT[x].devicename) + parallelports++; + } + if (serialports > 7) /* 3 bits -- maximum value = 7 */ + serialports=7; + if (parallelports > 3) /* 2 bits -- maximum value = 3 */ + parallelports=3; + + AX_reg(&context) = (diskdrives << 6) | (serialports << 9) | + (parallelports << 14) | 0x02; } diff --git a/multimedia/audio.c b/multimedia/audio.c index 5c46e07fd96..4c968093691 100644 --- a/multimedia/audio.c +++ b/multimedia/audio.c @@ -138,7 +138,6 @@ static DWORD WAVE_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpPa lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName); dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName); -/* printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */ if (strlen(lpstrElementName) > 0) { strcpy(str, lpstrElementName); AnsiUpper(str); diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c index dc99c2abc13..c8960709645 100644 --- a/multimedia/mcistring.c +++ b/multimedia/mcistring.c @@ -46,7 +46,7 @@ LONG ANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, /* The reason why I just don't lowercase the keywords array in * mciSendString is left as an exercise to the reader. */ -#define STRCMP(x,y) strcasecmp(x,y) +#define STRCMP(x,y) lstrcmpi(x,y) /* standard functionparameters for all functions */ #define _MCISTR_PROTO_ \ diff --git a/multimedia/midi.c b/multimedia/midi.c index b734ecdf71c..00941155c36 100644 --- a/multimedia/midi.c +++ b/multimedia/midi.c @@ -296,7 +296,6 @@ static DWORD MIDI_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS lpParms) if (dwFlags & MCI_OPEN_ELEMENT) { lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName); dprintf_midi(stddeb, "MIDI_mciOpen // MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName); -/* dprintf_midi(stddeb, "MIDI_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */ if (strlen(lpstrElementName) > 0) { strcpy(str, lpstrElementName); AnsiUpper(str); diff --git a/objects/font.c b/objects/font.c index 407d15e8d0b..b3df1a2160a 100644 --- a/objects/font.c +++ b/objects/font.c @@ -14,6 +14,7 @@ static char Copyright[] = "Copyright Alexandre Julliard, 1993"; #include "metafile.h" #include "wine.h" #include "callback.h" +#include "xmalloc.h" #include "stddebug.h" #include "debug.h" @@ -67,15 +68,15 @@ BOOL FONT_Init( void ) if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) { for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 ) if( strcmp( ptr, "default" ) ) - FontNames[i++].window = strdup( ptr ); + FontNames[i++].window = xstrdup( ptr ); FontSize = i; for( i = 1; i < FontSize; i++ ) { GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI); - FontNames[i].x11 = strdup( temp ); + FontNames[i].x11 = xstrdup( temp ); } GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI); - FontNames[0].x11 = strdup( temp ); + FontNames[0].x11 = xstrdup( temp ); } else { FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica"; diff --git a/tools/build.c b/tools/build.c index c2571e0dbef..e9667ad67ca 100644 --- a/tools/build.c +++ b/tools/build.c @@ -789,6 +789,7 @@ static void BuildSpec32Files( char *specname ) case TYPE_CDECL: varargs=0; argc=strlen(fdp->arg_types); +#if 0 if(odp->type == TYPE_STDCALL) { /* Output a function prototype with stdcall attribute */ @@ -810,22 +811,34 @@ static void BuildSpec32Files( char *specname ) } printf( ") __attribute((stdcall));\n" ); } - +#endif printf( "void %s_%d(", UpperDLLName, i); for(argno=0;argnotype == TYPE_STDCALL) { + switch(fdp->arg_types[argno]) + { + case 'p': printf( "void *");break; + case 'l': printf( "int ");break; + default: + fprintf(stderr, "Not supported argument type %c\n", + fdp->arg_types[argno]); + exit(1); + } + } else { switch(fdp->arg_types[argno]) { case 'p': printf( "void *");break; case 'l': printf( "int ");break; case '.': printf( "... ");varargs=argno;break; - default: + default: fprintf(stderr, "Not supported argument type %c\n", fdp->arg_types[argno]); exit(1); } - if(fdp->arg_types[argno]!='.') putchar( 'a'+argno ); - if (argno!=argc-1) putchar( ',' ); + } + if(fdp->arg_types[argno]!='.') putchar( 'a'+argno ); + if (argno!=argc-1) putchar( ',' ); } printf( ")" ); printf( "\n{\n" ); @@ -849,7 +862,14 @@ static void BuildSpec32Files( char *specname ) else putchar('a'+argno); if (argno!=argc-1) putchar(','); } - printf( ");\n}\n\n"); + printf( ");\n"); + if(odp->type == TYPE_STDCALL) { + printf( "\t__asm__ __volatile__ (\"movl %%ebp,%%esp\");\n"); + printf( "\t__asm__ __volatile__ (\"popl %%ebp\");\n"); + printf( "\t__asm__ __volatile__ (\"addl $%d,%%esp\");\n", argc*4+4); + printf( "\t__asm__ __volatile__ (\"jmp -%d(%%esp)\");\n", argc*4+4); + } + printf( "}\n\n"); break; case TYPE_RETURN: printf( "void %s_%d()\n{\n\t", UpperDLLName, i); diff --git a/win32/Makefile.in b/win32/Makefile.in index 3980b9efb5d..9851ec68166 100644 --- a/win32/Makefile.in +++ b/win32/Makefile.in @@ -8,12 +8,16 @@ C_SRCS = \ environment.c \ error.c \ file.c \ + heap.c \ init.c \ memory.c \ + newfns.c \ object_mgt.c \ process.c \ + resource.c \ thread.c \ - time.c + time.c \ + winprocs.c all: $(MODULE).o diff --git a/win32/file.c b/win32/file.c index 2188ff55d65..1dd15bcd02d 100644 --- a/win32/file.c +++ b/win32/file.c @@ -60,9 +60,6 @@ WINAPI HANDLE32 CreateFileMapping(HANDLE32 h,SECURITY_ATTRIBUTES *ats, return INVALID_HANDLE_VALUE; } fd = open(lpName, O_CREAT, 0666); - #if 0 - fd = open(DOS_GetUnixFileName(lpName), 0, 0666); - #endif if(fd == -1) { SetLastError(ErrnoToLastError(errno)); @@ -374,13 +371,13 @@ HANDLE32 CreateFileA(LPSTR filename, DWORD access, DWORD sharing, } else { + const char *unixName = DOSFS_GetUnixFileName( filename, FALSE ); type = FILE_TYPE_DISK; /* Try to open the file. */ - fd = open(DOS_GetUnixFileName(filename), - access_flags | create_flags, 0666); - if(fd == -1) + if (!unixName || + ((fd = open(unixName, access_flags | create_flags, 0666)) == -1)) { SetLastError(ErrnoToLastError(errno)); return INVALID_HANDLE_VALUE; @@ -406,6 +403,15 @@ HANDLE32 CreateFileA(LPSTR filename, DWORD access, DWORD sharing, return (HANDLE32)file_obj; } +/************************************************************************* + * W32_SetHandleCount (KERNEL32.??) + * + */ +UINT W32_SetHandleCount(UINT cHandles) +{ + return SetHandleCount(cHandles); +} + int CloseFileHandle(FILE_OBJECT *hFile) { /* If it's one of the 3 standard handles, don't really diff --git a/win32/heap.c b/win32/heap.c new file mode 100644 index 00000000000..7a4468fbab1 --- /dev/null +++ b/win32/heap.c @@ -0,0 +1,38 @@ +/* + * Win32 kernel functions + * + * Copyright 1995 Thomas Sandford + */ + +#include +#include +#include +#include +#include +#include +#include "windows.h" +#include "winerror.h" +#include "kernel32.h" +#include "winbase.h" +#include "stddebug.h" +#include "debug.h" + +#define HEAP_ZERO_MEMORY 0x8 + +/* FIXME: these functions do *not* implement the win32 API properly. They +are here merely as "get you going" aids */ + +/*********************************************************************** + * HeapAlloc (KERNEL32.222) + * + */ +LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes) + +{ + void *result; + + result = malloc(dwBytes); + if(result && (dwFlags & HEAP_ZERO_MEMORY)) + memset(result, 0, dwBytes); + return result; +} diff --git a/win32/init.c b/win32/init.c index d2e89369d87..2081fe1ebbd 100644 --- a/win32/init.c +++ b/win32/init.c @@ -11,6 +11,7 @@ #include "winerror.h" #include "kernel32.h" #include "handle32.h" +#include "pe_image.h" #include "stddebug.h" #define DEBUG_WIN32 #include "debug.h" @@ -72,10 +73,13 @@ DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) */ HMODULE WIN32_GetModuleHandle(char *module) { - if(module == NULL) - return (HMODULE)0; - else - return GetModuleHandle(module); + HMODULE hModule; + + dprintf_win32(stddeb, "GetModuleHandle: %s\n", module ? module : "NULL"); + if (module == NULL) hModule = GetExePtr( GetCurrentTask() ); + else hModule = GetModuleHandle(module); + dprintf_win32(stddeb, "GetModuleHandle: returning %d\n", hModule ); + return hModule; } /*********************************************************************** @@ -88,6 +92,7 @@ VOID GetStartupInfoA(LPSTARTUPINFO lpStartupInfo) lpStartupInfo->lpDesktop = "Desktop"; lpStartupInfo->lpTitle = "Title"; + lpStartupInfo->cbReserved2 = 0; lpStartupInfo->lpReserved2 = NULL; /* must be NULL for VC runtime */ lpStartupInfo->hStdInput = (HANDLE)0; lpStartupInfo->hStdOutput = (HANDLE)1; diff --git a/win32/memory.c b/win32/memory.c index 352db665bf4..bd55c2b874f 100644 --- a/win32/memory.c +++ b/win32/memory.c @@ -49,12 +49,20 @@ LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize, if (fdwAllocationType & MEM_RESERVE || !lpvAddress) { ptr = mmap((void *)((((unsigned long)lpvAddress-1) & 0xFFFF0000L) + 0x00010000L), - cbSize, PROT_NONE, MAP_ANON|MAP_PRIVATE,0,0); + cbSize, PROT_NONE, MAP_ANON|MAP_PRIVATE,-1,0); + if (ptr == (caddr_t) -1) { + dprintf_win32(stddeb, "VirtualAlloc: returning NULL"); + return (LPVOID) NULL; + } if (lpvAddress && ((unsigned long)ptr & 0xFFFF0000L)) { munmap(ptr, cbSize); cbSize += 65535; ptr = mmap(lpvAddress, cbSize, - PROT_NONE, MAP_ANON|MAP_PRIVATE,0,0); + PROT_NONE, MAP_ANON|MAP_PRIVATE,-1,0); + if (ptr == (caddr_t) -1) { + dprintf_win32(stddeb, "VirtualAlloc: returning NULL"); + return (LPVOID) NULL; + } ptr = (void *)((((unsigned long)ptr-1) & 0xFFFF0000L)+0x00010000L); } /* remember the size for VirtualFree since it's going to be handed @@ -84,7 +92,6 @@ LPVOID VirtualAlloc(LPVOID lpvAddress, DWORD cbSize, ~(PAGE_GUARD | PAGE_NOCACHE)); mprotect(ptr, cbSize, prot); } - return ptr; #if 0 /* kludge for gnu-win32 */ if (fdwAllocationType & MEM_RESERVE) return sbrk(0); diff --git a/win32/newfns.c b/win32/newfns.c new file mode 100644 index 00000000000..2f2fe449d78 --- /dev/null +++ b/win32/newfns.c @@ -0,0 +1,47 @@ +/* + * Win32 miscellaneous functions + * + * Copyright 1995 Thomas Sandford (tdgsandf@prds-grn.demon.co.uk) + */ + +/* Misc. new functions - they should be moved into appropriate files +at a later date. */ + +#include +#include "windows.h" +#include "winerror.h" +#include "kernel32.h" +#include "stddebug.h" +#include "debug.h" + +/*********************************************************************** + * RaiseException (KERNEL32.??) + * + * Stub function - does not allow exceptions to be caught yet + */ +WINAPI VOID RaiseException(DWORD dwExceptionCode, + DWORD dwExceptionFlags, + DWORD cArguments, + const DWORD * lpArguments) +{ + ExitProcess(dwExceptionCode); /* what status should be used here ? */ +} + +/*********************************************************************** + * GetProcAddress (KERNEL32.257) + * + */ +WINAPI FARPROC W32_GetProcAddress(HMODULE hModule, + LPCSTR lpszProc) +{ + char *modulename; + + modulename = MODULE_GetModuleName(hModule); + if (modulename == NULL) + return (FARPROC) NULL; + if (((int) lpszProc) & 0xffff) + return RELAY32_GetEntryPoint(modulename, lpszProc, 0); + else + return RELAY32_GetEntryPoint(modulename, (char *) NULL, (int) lpszProc); +} + diff --git a/win32/process.c b/win32/process.c index 8fb8fe4c5b7..b8e244db9aa 100644 --- a/win32/process.c +++ b/win32/process.c @@ -82,3 +82,40 @@ HANDLE32 WINAPI GetCurrentProcess(void) { return 0; } + +/*********************************************************************** + * LoadLibraryA (KERNEL32.365) + * copied from LoadLibrary + * This does not currently support built-in libraries + */ +HANDLE32 WINAPI LoadLibraryA(char *libname) +{ + HANDLE handle; + dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname); + handle = LoadModule( libname, (LPVOID)-1 ); + if (handle == (HANDLE) -1) + { + char buffer[256]; + strcpy( buffer, libname ); + strcat( buffer, ".dll" ); + handle = LoadModule( buffer, (LPVOID)-1 ); + } + /* Obtain module handle and call initialization function */ +#ifndef WINELIB + if (handle >= (HANDLE)32) PE_InitializeDLLs( GetExePtr(handle)); +#endif + return handle; +} + + +#ifndef WINELIB +/*********************************************************************** + * WIN32_GetProcAddress + */ +void* WINAPI WIN32_GetProcAddress(HANDLE32 hModule, char* function) +{ + dprintf_module( stddeb, "WIN32_GetProcAddress(%08x,%s)\n", + hModule, function); + return PE_GetProcAddress(GetExePtr(hModule),function); +} +#endif /* WINELIB */ diff --git a/win32/resource.c b/win32/resource.c new file mode 100644 index 00000000000..5add4406039 --- /dev/null +++ b/win32/resource.c @@ -0,0 +1,353 @@ +/* + * Win32 Resources + * + * Copyright 1995 Thomas Sandford + * + * Based on the Win16 resource handling code in loader/resource.c + * Copyright 1993 Robert J. Amstadt + * Copyright 1995 Alexandre Julliard + * + * This is not even at ALPHA level yet. Don't expect it to work! + */ + +#include +#include "wintypes.h" +#include "windows.h" +#include "kernel32.h" +#include "pe_image.h" +#include "handle32.h" +#include "resource32.h" +#include "neexe.h" +#include "accel.h" +#include "xmalloc.h" +#include "stddebug.h" +#include "debug.h" + +int language = 0x0409; + +#define PrintId(name) \ + if (HIWORD((DWORD)name)) \ + dprintf_resource( stddeb, "'%s'", name); \ + else \ + dprintf_resource( stddeb, "#%04x", LOWORD(name)); + +/********************************************************************** + * GetResDirEntry + * + * Helper function - goes down one level of PE resource tree + * + */ +PIMAGE_RESOURCE_DIRECTORY GetResDirEntry(PIMAGE_RESOURCE_DIRECTORY resdirptr, + LPCSTR name, + DWORD root) +{ + int entrynum; + PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable; + + if (HIWORD(name)) { + /* FIXME: what about #xxx names? */ + entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ( + (BYTE *) resdirptr + + sizeof(IMAGE_RESOURCE_DIRECTORY)); + for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++) + /* do what??? */ ; + return NULL; + } else { + entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ( + (BYTE *) resdirptr + + sizeof(IMAGE_RESOURCE_DIRECTORY) + + resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); + for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++) + if ((DWORD)entryTable[entrynum].Name == (DWORD)name) + return (PIMAGE_RESOURCE_DIRECTORY) ( + root + + (entryTable[entrynum].OffsetToData & 0x7fffffff)); + return NULL; + } +} + +/********************************************************************** + * FindResource (KERNEL.60) + */ +HANDLE32 FindResource32( HINSTANCE hModule, LPCTSTR name, LPCTSTR type ) +{ +#ifndef WINELIB + struct w_files *wptr = wine_files; + PIMAGE_RESOURCE_DIRECTORY resdirptr; + DWORD root; + +#if 0 + hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ +#endif + dprintf_resource(stddeb, "FindResource: module=%08x type=", hModule ); + PrintId( type ); + dprintf_resource( stddeb, " name=" ); + PrintId( name ); + dprintf_resource( stddeb, "\n" ); + while (wptr != NULL && (wptr->hModule != hModule)) + wptr = wptr->next; + if ((wptr == NULL) || (wptr->pe == NULL) || (wptr->pe->pe_resource == NULL)) + return 0; + resdirptr = (PIMAGE_RESOURCE_DIRECTORY) wptr->pe->pe_resource; + root = (DWORD) resdirptr; + if ((resdirptr = GetResDirEntry(resdirptr, type, root)) == NULL) + return 0; + if ((resdirptr = GetResDirEntry(resdirptr, name, root)) == NULL) + return 0; + return (HANDLE32) GetResDirEntry(resdirptr, (LPCSTR)language, root); +#else + return LIBRES_FindResource( hModule, name, type ); +#endif +} + + +/********************************************************************** + * LoadResource (KERNEL.61) + */ +HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc ) +{ +#ifndef WINELIB + struct w_files *wptr = wine_files; + +#if 0 + hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ +#endif + dprintf_resource(stddeb, "LoadResource: module="NPFMT" res="NPFMT"\n", + hModule, hRsrc ); + if (!hRsrc) return 0; + while (wptr != NULL && (wptr->hModule != hModule)) + wptr = wptr->next; + if ((wptr == NULL) || (wptr->pe == NULL) || (wptr->pe->pe_resource == NULL)) + return 0; + return (HANDLE32) (wptr->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData); +#else + return LIBRES_LoadResource( hModule, hRsrc ); +#endif +} + + +/********************************************************************** + * LockResource (KERNEL.62) + */ +LPVOID LockResource32( HANDLE32 handle ) +{ + return (LPVOID) handle; +} + +/********************************************************************** + * FreeResource (KERNEL.63) + */ +BOOL FreeResource32( HANDLE32 handle ) +{ + /* no longer used in Win32 */ + return TRUE; +} + +/********************************************************************** + * AccessResource (KERNEL.64) + */ +INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc ) +{ + WORD *pModule; + + hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ + dprintf_resource(stddeb, "AccessResource: module="NPFMT" res="NPFMT"\n", + hModule, hRsrc ); + if (!hRsrc) return 0; + if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0; +#ifndef WINELIB + switch(*pModule) + { + case NE_SIGNATURE: + return NE_AccessResource( hModule, hRsrc ); + case PE_SIGNATURE: + return 0; + default: + return 0; + } +#else + return LIBRES_AccessResource( hModule, hRsrc ); +#endif +} + + +/********************************************************************** + * SizeofResource (KERNEL.65) + */ +DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc ) +{ + WORD *pModule; + + hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ + dprintf_resource(stddeb, "SizeofResource: module="NPFMT" res="NPFMT"\n", + hModule, hRsrc ); + if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0; +#ifndef WINELIB + switch(*pModule) + { + case NE_SIGNATURE: + return NE_SizeofResource( hModule, hRsrc ); + case PE_SIGNATURE: + return 0; + default: + return 0; + } +#else + return LIBRES_SizeofResource( hModule, hRsrc ); +#endif +} + +/********************************************************************** + * LoadAccelerators [USER.177] +*/ +HANDLE LoadAccelerators32(HINSTANCE instance, LPCTSTR lpTableName) +{ + HANDLE hAccel; + HANDLE rsc_mem; + HRSRC hRsrc; + BYTE *lp; + ACCELHEADER *lpAccelTbl; + int i, n; + + if (HIWORD(lpTableName)) + dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" '%s'\n", + instance, (char *)( lpTableName ) ); + else + dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" %04x\n", + instance, LOWORD(lpTableName) ); + + if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR ))) + return 0; + if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0; + + lp = (BYTE *)LockResource(rsc_mem); + n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY); + hAccel = GlobalAlloc(GMEM_MOVEABLE, + sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY)); + lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel); + lpAccelTbl->wCount = 0; + for (i = 0; i < n; i++) { + lpAccelTbl->tbl[i].type = *(lp++); + lpAccelTbl->tbl[i].wEvent = *((WORD *)lp); + lp += 2; + lpAccelTbl->tbl[i].wIDval = *((WORD *)lp); + lp += 2; + if (lpAccelTbl->tbl[i].wEvent == 0) break; + dprintf_accel(stddeb, + "Accelerator #%u / event=%04X id=%04X type=%02X \n", + i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, + lpAccelTbl->tbl[i].type); + lpAccelTbl->wCount++; + } + GlobalUnlock(hAccel); + FreeResource( rsc_mem ); + return hAccel; +} + +/********************************************************************** + * LoadString + */ +int +LoadString32(HINSTANCE instance, DWORD resource_id, LPTSTR buffer, int buflen) +{ + HANDLE32 hmem, hrsrc; + WCHAR *p; + int string_num; + int i; + + dprintf_resource(stddeb, "LoadString: instance = "NPFMT", id = %04x, buffer = %08x, " + "length = %d\n", instance, resource_id, (int) buffer, buflen); + + hrsrc = FindResource32( instance, (resource_id>>4)+1, RT_STRING ); + if (!hrsrc) return 0; + hmem = LoadResource32( instance, hrsrc ); + if (!hmem) return 0; + + p = LockResource32(hmem); + string_num = resource_id & 0x000f; + for (i = 0; i < string_num; i++) + p += *p + 1; + + dprintf_resource( stddeb, "strlen = %d\n", (int)*p ); + + i = MIN(buflen - 1, *p); + if (buffer == NULL) + return i; + if (i > 0) { + memcpy(buffer, p + 1, i * sizeof (WCHAR)); + buffer[i] = (WCHAR) 0; + } else { + if (buflen > 1) { + buffer[0] = (WCHAR) 0; + return 0; + } + fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p); + fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1); + } + dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer); + return i; +} + +/********************************************************************** + * LoadStringA + */ +int +LoadStringA32(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen) +{ + WCHAR *buffer2 = xmalloc(buflen*2); + int retval = LoadString32(instance, resource_id, buffer2, buflen); + + while (*buffer2) + *buffer++ = (char) *buffer2++; + *buffer = 0; + return retval; +} + +HICON LoadIconW32(HINSTANCE hisnt, LPCTSTR lpszIcon) + +{ + return LoadIcon(0, IDI_APPLICATION); +} + +HICON LoadIconA32(HINSTANCE hinst, LPCTSTR lpszIcon) + +{ + return LoadIconW32(hinst, lpszIcon); +} +/********************************************************************** + * LoadBitmapW + */ +HBITMAP LoadBitmapW32( HANDLE instance, LPCTSTR name ) +{ + HBITMAP hbitmap = 0; + HDC hdc; + HANDLE32 hRsrc; + HANDLE32 handle; + BITMAPINFO *info; + + if (!instance) /* OEM bitmap */ + { + if (HIWORD((int)name)) return 0; + return OBM_LoadBitmap( LOWORD((int)name) ); + } + + if (!(hRsrc = FindResource32( instance, name, RT_BITMAP ))) return 0; + if (!(handle = LoadResource32( instance, hRsrc ))) return 0; + + info = (BITMAPINFO *)LockResource32( handle ); + if ((hdc = GetDC(0)) != 0) + { + char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS ); + hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT, + bits, info, DIB_RGB_COLORS ); + ReleaseDC( 0, hdc ); + } + return hbitmap; +} +/********************************************************************** + * LoadBitmapA + */ +HBITMAP LoadBitmapA32( HANDLE instance, LPCTSTR name ) +{ + return LoadBitmapW32(instance, name); +} diff --git a/win32/winprocs.c b/win32/winprocs.c new file mode 100644 index 00000000000..1d9d5a232ae --- /dev/null +++ b/win32/winprocs.c @@ -0,0 +1,241 @@ +/* + * Win32 WndProc function stubs + * + * Copyright 1995 Thomas Sandford (tdgsandf@prds-grn.demon.co.uk) + * + * These functions are simply lParam fixers for the Win16 routines + */ + +#include +#include "windows.h" +#include "winerror.h" +#include "kernel32.h" +#include "wincon.h" +#include "stackframe.h" +#include "stddebug.h" +#include "debug.h" + +BOOL UsesLParamPtr(DWORD message) + +{ + switch (message) { + case WM_NCCREATE: + case WM_NCCALCSIZE: + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + case WM_GETTEXT: + case WM_SETTEXT: + case WM_GETMINMAXINFO: + return TRUE; + default: + return FALSE; + } +} + +LRESULT USER32_DefWindowProcA(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return DefWindowProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return DefWindowProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ButtonWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ButtonWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ButtonWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT StaticWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return StaticWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return StaticWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ScrollBarWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ScrollBarWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ScrollBarWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ListBoxWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ListBoxWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ListBoxWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ComboBoxWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ComboBoxWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ComboBoxWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT EditWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return EditWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return EditWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT PopupMenuWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return PopupMenuWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return PopupMenuWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT DesktopWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return DesktopWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return DesktopWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT DefDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return DefDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return DefDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT MDIClientWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return MDIClientWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return MDIClientWndProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT DefWindowProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return DefWindowProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return DefWindowProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT DefMDIChildProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return DefMDIChildProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return DefMDIChildProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT SystemMessageBoxProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return SystemMessageBoxProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return SystemMessageBoxProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT FileOpenDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return FileOpenDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return FileOpenDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT FileSaveDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return FileSaveDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return FileSaveDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ColorDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ColorDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ColorDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT FindTextDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return FindTextDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return FindTextDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ReplaceTextDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ReplaceTextDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ReplaceTextDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT PrintSetupDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return PrintSetupDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return PrintSetupDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT PrintDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return PrintDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return PrintDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT AboutDlgProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return AboutDlgProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return AboutDlgProc((HWND)hwnd, msg, wParam, lParam); +} + +LRESULT ComboLBoxWndProc32(DWORD hwnd, DWORD msg, DWORD wParam, DWORD lParam) + +{ + if (UsesLParamPtr(msg)) + return ComboLBoxWndProc((HWND)hwnd, msg, wParam, MAKE_SEGPTR((void *)lParam)); + else + return ComboLBoxWndProc((HWND)hwnd, msg, wParam, lParam); +} + diff --git a/windows/dce.c b/windows/dce.c index 15ea23276c2..04d90ae178a 100644 --- a/windows/dce.c +++ b/windows/dce.c @@ -146,7 +146,7 @@ static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect ) static HRGN DCE_ClipWindows( HWND hwndStart, HWND hwndEnd, HRGN hrgn, int xoffset, int yoffset ) { - HRGN hrgnTmp, hrgnNew; + HRGN hrgnTmp = 0, hrgnNew = 0; WND *wndPtr; if (!hwndStart) return hrgn; diff --git a/windows/message.c b/windows/message.c index 43bb4e4e9d3..458232c9307 100644 --- a/windows/message.c +++ b/windows/message.c @@ -30,6 +30,8 @@ extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg, HWND hwnd, BOOL remove ); /* timer.c */ +DWORD MSG_WineStartTicks; /* Ticks at Wine startup */ + /* ------- Internal Queues ------ */ static HANDLE hmemSysMsgQueue = 0; @@ -1243,12 +1245,14 @@ LONG DispatchMessage( LPMSG msg ) /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */ retval = CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message, msg->wParam, msg->lParam ); - if (painting && IsWindow(msg->hwnd) && - (wndPtr->flags & WIN_NEEDS_BEGINPAINT)) + if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) && + (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate) { fprintf(stderr, "BeginPaint not called on WM_PAINT for hwnd "NPFMT"!\n", msg->hwnd); wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT; + /* Validate the update region to avoid infinite WM_PAINT loop */ + ValidateRect( msg->hwnd, NULL ); } return retval; } @@ -1307,7 +1311,7 @@ DWORD GetTickCount(void) { struct timeval t; gettimeofday( &t, NULL ); - return (t.tv_sec * 1000) + (t.tv_usec / 1000); + return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks; } /*********************************************************************** diff --git a/windows/property.c b/windows/property.c index 1dcafb82d55..92d1748f660 100644 --- a/windows/property.c +++ b/windows/property.c @@ -70,7 +70,7 @@ HANDLE GetProp( HWND hwnd, SEGPTR str ) PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR(hProp); if (HIWORD(str)) { - if (!prop->atom && !strcasecmp( prop->string, PTR_SEG_TO_LIN(str))) + if (!prop->atom && !lstrcmpi( prop->string, PTR_SEG_TO_LIN(str))) return prop->hData; } else if (prop->atom && (prop->atom == LOWORD(str))) return prop->hData; @@ -95,7 +95,7 @@ HANDLE RemoveProp( HWND hwnd, SEGPTR str ) { PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR( *hProp ); if ((HIWORD(str) && !prop->atom && - !strcasecmp( prop->string, PTR_SEG_TO_LIN(str))) || + !lstrcmpi( prop->string, PTR_SEG_TO_LIN(str))) || (!HIWORD(str) && prop->atom && (prop->atom == LOWORD(str)))) { HANDLE hNext = prop->next; diff --git a/windows/win.c b/windows/win.c index da50aec5734..1c7d8953601 100644 --- a/windows/win.c +++ b/windows/win.c @@ -13,7 +13,6 @@ #include "user.h" #include "dce.h" #include "sysmetrics.h" -#include "menu.h" #include "cursoricon.h" #include "event.h" #include "message.h" @@ -481,6 +480,8 @@ HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName, } else wndPtr->wIDmenu = (UINT)menu; + GetSystemMenu( hwnd, TRUE ); /* Create a copy of the system menu */ + /* Send the WM_CREATE message */ createStruct.lpCreateParams = (LPSTR)data; @@ -517,9 +518,6 @@ HWND CreateWindowEx( DWORD exStyle, SEGPTR className, SEGPTR windowName, return 0; } - /* Create a copy of SysMenu */ - if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu(); - WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd ); /* Show the window, maximizing or minimizing if needed */ diff --git a/windows/winpos.c b/windows/winpos.c index 659cd2f963f..3a7eb9f7262 100644 --- a/windows/winpos.c +++ b/windows/winpos.c @@ -434,6 +434,7 @@ BOOL ShowWindow( HWND hwnd, int cmd ) if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE; /* fall through */ case SW_SHOWNORMAL: /* same as SW_NORMAL: */ + case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ case SW_RESTORE: swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;