Release 980503
[wine/hacks.git] / loader / module.c
blob63568eebd40684ab3967a34cf101773c4a4d4fcd
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include "windows.h"
15 #include "class.h"
16 #include "file.h"
17 #include "global.h"
18 #include "heap.h"
19 #include "module.h"
20 #include "neexe.h"
21 #include "pe_image.h"
22 #include "process.h"
23 #include "thread.h"
24 #include "resource.h"
25 #include "selectors.h"
26 #include "stackframe.h"
27 #include "task.h"
28 #include "toolhelp.h"
29 #include "debug.h"
30 #include "callback.h"
32 extern BOOL32 THREAD_InitDone;
34 extern HMODULE16 hFirstModule; /* FIXME */
35 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
37 static HMODULE32 MODULE_LoadModule(LPCSTR name,BOOL32 force) { return 0; }
38 HMODULE32 (*fnBUILTIN_LoadModule)(LPCSTR name,BOOL32 force) = MODULE_LoadModule;
41 /*************************************************************************
42 * MODULE32_LookupHMODULE
43 * looks for the referenced HMODULE in the current process
45 WINE_MODREF*
46 MODULE32_LookupHMODULE(PDB32 *process,HMODULE32 hmod) {
47 WINE_MODREF *wm;
49 if (!hmod)
50 return process->exe_modref;
51 if (!HIWORD(hmod)) {
52 ERR(module,"tried to lookup 0x%04x in win32 module handler!\n",hmod);
53 return NULL;
55 for (wm = process->modref_list;wm;wm=wm->next)
56 if (wm->module == hmod)
57 return wm;
58 return NULL;
61 /***********************************************************************
62 * MODULE_GetPtr16
64 NE_MODULE *MODULE_GetPtr16( HMODULE16 hModule )
66 return (NE_MODULE*)GlobalLock16( GetExePtr(hModule) );
70 /***********************************************************************
71 * MODULE_GetPtr32
73 NE_MODULE *MODULE_GetPtr32( HMODULE32 hModule )
75 return (NE_MODULE*)GlobalLock16( MODULE_HANDLEtoHMODULE16(hModule) );
78 /***********************************************************************
79 * MODULE_HANDLEtoHMODULE16
81 HMODULE16
82 MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
83 NE_MODULE *pModule;
85 if (HIWORD(handle))
87 WARN(module,"looking up 0x%08x in win16 function!\n",handle);
88 /* this is a HMODULE32 */
90 /* walk the list looking for the correct startaddress */
91 pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
92 while (pModule)
94 if (pModule->module32 == handle) return pModule->self;
95 pModule = (NE_MODULE*)GlobalLock16(pModule->next);
97 return 0;
99 return GetExePtr(handle);
102 /***********************************************************************
103 * MODULE_OpenFile
105 int MODULE_OpenFile( HMODULE32 hModule )
107 NE_MODULE *pModule;
108 DOS_FULL_NAME full_name;
109 char *name;
111 static int cachedfd = -1;
113 hModule = MODULE_HANDLEtoHMODULE16(hModule);
114 TRACE(module, "(%04x) cache: mod=%04x fd=%d\n",
115 hModule, hCachedModule, cachedfd );
116 if (!(pModule = MODULE_GetPtr32( hModule ))) return -1;
117 if (hCachedModule == hModule) return cachedfd;
118 close( cachedfd );
119 hCachedModule = hModule;
120 name = NE_MODULE_NAME( pModule );
121 if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
122 (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
123 WARN( module, "Can't open file '%s' for module %04x\n",
124 name, hModule );
125 TRACE(module, "opened '%s' -> %d\n",
126 name, cachedfd );
127 return cachedfd;
131 /***********************************************************************
132 * MODULE_CreateInstance
134 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
136 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, HINSTANCE16 *prev,
137 BOOL32 lib_only )
139 SEGTABLEENTRY *pSegment;
140 NE_MODULE *pModule;
141 int minsize;
142 HINSTANCE16 hNewInstance;
144 if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
145 if (pModule->dgroup == 0)
147 if (prev) *prev = hModule;
148 return hModule;
151 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
152 if (prev) *prev = pSegment->selector;
154 /* if it's a library, create a new instance only the first time */
155 if (pSegment->selector)
157 if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
158 if (lib_only) return pSegment->selector;
161 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
162 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
163 minsize += pModule->heap_size;
164 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
165 minsize, hModule, FALSE, FALSE, FALSE );
166 if (!hNewInstance) return 0;
167 pSegment->selector = hNewInstance;
168 return hNewInstance;
172 /***********************************************************************
173 * MODULE_CreateDummyModule
175 * Create a dummy NE module for Win32 or Winelib.
177 HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
179 HMODULE32 hModule;
180 NE_MODULE *pModule;
181 SEGTABLEENTRY *pSegment;
182 char *pStr,*s;
183 int len;
184 const char* basename;
186 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
187 + strlen(ofs->szPathName) + 1;
188 INT32 size = sizeof(NE_MODULE) +
189 /* loaded file info */
190 of_size +
191 /* segment table: DS,CS */
192 2 * sizeof(SEGTABLEENTRY) +
193 /* name table */
195 /* several empty tables */
198 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
199 if (!hModule) return (HMODULE32)11; /* invalid exe */
201 FarSetOwner( hModule, hModule );
202 pModule = (NE_MODULE *)GlobalLock16( hModule );
204 /* Set all used entries */
205 pModule->magic = IMAGE_OS2_SIGNATURE;
206 pModule->count = 1;
207 pModule->next = 0;
208 pModule->flags = 0;
209 pModule->dgroup = 1;
210 pModule->ss = 1;
211 pModule->cs = 2;
212 pModule->heap_size = 0xe000;
213 pModule->stack_size = 0x1000;
214 pModule->seg_count = 2;
215 pModule->modref_count = 0;
216 pModule->nrname_size = 0;
217 pModule->fileinfo = sizeof(NE_MODULE);
218 pModule->os_flags = NE_OSFLAGS_WINDOWS;
219 pModule->expected_version = 0x030a;
220 pModule->self = hModule;
222 /* Set loaded file information */
223 memcpy( pModule + 1, ofs, of_size );
224 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
226 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
227 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
228 /* Data segment */
229 pSegment->size = 0;
230 pSegment->flags = NE_SEGFLAGS_DATA;
231 pSegment->minsize = 0x1000;
232 pSegment++;
233 /* Code segment */
234 pSegment->flags = 0;
235 pSegment++;
237 /* Module name */
238 pStr = (char *)pSegment;
239 pModule->name_table = (int)pStr - (int)pModule;
240 basename = strrchr(ofs->szPathName,'\\');
241 if (!basename) basename = ofs->szPathName;
242 else basename++;
243 len = strlen(basename);
244 if ((s = strchr(basename,'.'))) len = s - basename;
245 if (len > 8) len = 8;
246 *pStr = len;
247 strncpy( pStr+1, basename, len );
248 if (len < 8) pStr[len+1] = 0;
249 pStr += 9;
251 /* All tables zero terminated */
252 pModule->res_table = pModule->import_table = pModule->entry_table =
253 (int)pStr - (int)pModule;
255 NE_RegisterModule( pModule );
256 return hModule;
260 /***********************************************************************
261 * MODULE_GetWndProcEntry16 (not a Windows API function)
263 * Return an entry point from the WPROCS dll.
265 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
267 FARPROC16 ret = NULL;
269 if (__winelib)
271 /* FIXME: hack for Winelib */
272 extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
273 extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
274 extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
275 extern LRESULT FindTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
276 extern LRESULT PrintDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
277 extern LRESULT PrintSetupDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
278 extern LRESULT ReplaceTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
280 if (!strcmp(name,"ColorDlgProc"))
281 return (FARPROC16)ColorDlgProc;
282 if (!strcmp(name,"FileOpenDlgProc"))
283 return (FARPROC16)FileOpenDlgProc;
284 if (!strcmp(name,"FileSaveDlgProc"))
285 return (FARPROC16)FileSaveDlgProc;
286 if (!strcmp(name,"FindTextDlgProc"))
287 return (FARPROC16)FindTextDlgProc16;
288 if (!strcmp(name,"PrintDlgProc"))
289 return (FARPROC16)PrintDlgProc;
290 if (!strcmp(name,"PrintSetupDlgProc"))
291 return (FARPROC16)PrintSetupDlgProc;
292 if (!strcmp(name,"ReplaceTextDlgProc"))
293 return (FARPROC16)ReplaceTextDlgProc16;
294 WARN(module,"No mapping for %s(), add one in library/miscstubs.c\n",name);
295 assert( FALSE );
296 return NULL;
298 else
300 WORD ordinal;
301 static HMODULE32 hModule = 0;
303 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
304 ordinal = NE_GetOrdinal( hModule, name );
305 if (!(ret = NE_GetEntryPoint( hModule, ordinal )))
307 WARN( module, "%s not found\n", name );
308 assert( FALSE );
311 return ret;
315 /***********************************************************************
316 * MODULE_GetModuleName
318 LPSTR MODULE_GetModuleName( HMODULE32 hModule )
320 NE_MODULE *pModule;
321 BYTE *p, len;
322 static char buffer[10];
324 if (!(pModule = MODULE_GetPtr32( hModule ))) return NULL;
325 p = (BYTE *)pModule + pModule->name_table;
326 len = MIN( *p, 8 );
327 memcpy( buffer, p + 1, len );
328 buffer[len] = '\0';
329 return buffer;
333 /**********************************************************************
334 * MODULE_FindModule
336 * Find a module from a path name.
337 * RETURNS
338 * the win16 module handle if found
339 * 0 if not
341 HMODULE32 MODULE_FindModule16(
342 LPCSTR path /* [in] path of the module to be found */
344 HMODULE32 hModule = hFirstModule;
345 LPCSTR filename, dotptr, modulepath, modulename;
346 BYTE len, *name_table;
348 if (!(filename = strrchr( path, '\\' ))) filename = path;
349 else filename++;
350 if ((dotptr = strrchr( filename, '.' )) != NULL)
351 len = (BYTE)(dotptr - filename);
352 else len = strlen( filename );
354 while(hModule)
356 NE_MODULE *pModule = MODULE_GetPtr16( hModule );
357 if (!pModule) break;
358 modulepath = NE_MODULE_NAME(pModule);
359 if (!(modulename = strrchr( modulepath, '\\' )))
360 modulename = modulepath;
361 else modulename++;
362 if (!lstrcmpi32A( modulename, filename )) return hModule;
364 name_table = (BYTE *)pModule + pModule->name_table;
365 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
366 return hModule;
367 hModule = pModule->next;
369 return 0;
372 /**********************************************************************
373 * MODULE_FindModule32
375 * Find a (loaded) win32 module depending on path
376 * The handling of '.' is a bit weird, but we need it that way,
377 * for sometimes the programs use '<name>.exe' and '<name>.dll' and
378 * this is the only way to differentiate. (mainly hypertrm.exe)
380 * RETURNS
381 * the module handle if found
382 * 0 if not
384 HMODULE32 MODULE_FindModule32(
385 PDB32* process, /* [in] process in which to find the library */
386 LPCSTR path /* [in] pathname of module/library to be found */
388 LPSTR filename;
389 LPSTR dotptr;
390 WINE_MODREF *wm;
392 if (!(filename = strrchr( path, '\\' )))
393 filename = HEAP_strdupA(process->heap,0,path);
394 else
395 filename = HEAP_strdupA(process->heap,0,filename+1);
396 dotptr=strrchr(filename,'.');
398 if (!process) {
399 HeapFree(process->heap,0,filename);
400 return 0;
402 for (wm=process->modref_list;wm;wm=wm->next) {
403 LPSTR xmodname,xdotptr;
405 assert (wm->modname);
406 xmodname = HEAP_strdupA(process->heap,0,wm->modname);
407 xdotptr=strrchr(xmodname,'.');
408 if ( (xdotptr && !dotptr) ||
409 (!xdotptr && dotptr)
411 if (dotptr) *dotptr = '\0';
412 if (xdotptr) *xdotptr = '\0';
414 if (!lstrcmpi32A( filename, xmodname)) {
415 HeapFree(process->heap,0,filename);
416 HeapFree(process->heap,0,xmodname);
417 return wm->module;
419 if (dotptr) *dotptr='.';
420 /* FIXME: add paths, shortname */
421 HeapFree(process->heap,0,xmodname);
423 HeapFree(process->heap,0,filename);
424 return 0;
429 /**********************************************************************
430 * MODULE_CallWEP
432 * Call a DLL's WEP, allowing it to shut down.
433 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
435 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
437 FARPROC16 WEP = (FARPROC16)0;
438 WORD ordinal = NE_GetOrdinal( hModule, "WEP" );
440 if (ordinal) WEP = NE_GetEntryPoint( hModule, ordinal );
441 if (!WEP)
443 WARN(module, "module %04x doesn't have a WEP\n", hModule );
444 return FALSE;
446 return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
450 /**********************************************************************
451 * MODULE_FreeModule
453 * Remove a module from memory.
455 BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
457 HMODULE16 *hPrevModule;
458 NE_MODULE *pModule;
459 SEGTABLEENTRY *pSegment;
460 HMODULE16 *pModRef;
461 int i;
463 if (!(pModule = MODULE_GetPtr32( hModule ))) return FALSE;
464 hModule = pModule->self;
466 if (((INT16)(--pModule->count)) > 0 ) return TRUE;
467 else pModule->count = 0;
469 if (pModule->flags & NE_FFLAGS_BUILTIN)
470 return FALSE; /* Can't free built-in module */
472 if (pModule->flags & NE_FFLAGS_LIBMODULE)
474 MODULE_CallWEP( hModule );
476 /* Free the objects owned by the DLL module */
478 if( pTaskContext && pTaskContext->userhandler )
480 pTaskContext->userhandler( hModule, USIG_DLL_UNLOAD, 0,
481 pTaskContext->hInstance,
482 pTaskContext->hQueue );
485 /* Clear magic number just in case */
487 pModule->magic = pModule->self = 0;
489 /* Remove it from the linked list */
491 hPrevModule = &hFirstModule;
492 while (*hPrevModule && (*hPrevModule != hModule))
494 hPrevModule = &(MODULE_GetPtr16( *hPrevModule ))->next;
496 if (*hPrevModule) *hPrevModule = pModule->next;
498 /* Free all the segments */
500 pSegment = NE_SEG_TABLE( pModule );
501 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
503 GlobalFree16( pSegment->selector );
506 /* Free the referenced modules */
508 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
509 for (i = 0; i < pModule->modref_count; i++, pModRef++)
511 FreeModule16( *pModRef );
514 /* Free the module storage */
516 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
517 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
518 GlobalFree16( hModule );
520 /* Remove module from cache */
522 if (hCachedModule == hModule) hCachedModule = 0;
524 return TRUE;
528 /**********************************************************************
529 * MODULE_Load
531 * Implementation of LoadModule().
533 * cmd_line must contain the whole command-line, including argv[0] (and
534 * without a preceding length byte).
535 * If cmd_line is NULL, the module is loaded as a library even if it is a .exe
537 HINSTANCE16 MODULE_Load( LPCSTR name, UINT16 uFlags,
538 LPCSTR cmd_line, LPCSTR env, UINT32 show_cmd )
540 HMODULE32 hModule;
541 HINSTANCE16 hInstance, hPrevInstance;
542 NE_MODULE *pModule;
543 OFSTRUCT ofs;
544 HFILE32 hFile;
546 if (__winelib)
548 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
549 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
550 pModule = (NE_MODULE *)GlobalLock16( hModule );
551 hInstance = MODULE_CreateInstance( hModule, &hPrevInstance,
552 (cmd_line == NULL) );
554 else
556 hModule = MODULE_FindModule16( name );
558 if (!hModule) /* We have to load the module */
560 /* Try to load the built-in first if not disabled */
561 if ((hModule = fnBUILTIN_LoadModule( name, FALSE )))
562 return MODULE_HANDLEtoHMODULE16( hModule );
564 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
566 /* Now try the built-in even if disabled */
567 if ((hModule = fnBUILTIN_LoadModule( name, TRUE )))
569 WARN(module, "Could not load Windows DLL '%s', using built-in module.\n", name );
570 return MODULE_HANDLEtoHMODULE16( hModule );
572 return 2; /* File not found */
575 /* Create the module structure */
577 hModule = NE_LoadModule( hFile, &ofs, uFlags, cmd_line,
578 env, show_cmd );
579 if (hModule < 32)
581 if ((hModule == 21) && cmd_line)
582 hModule = PE_LoadModule( hFile, &ofs, cmd_line,
583 env, show_cmd );
586 if (hModule < 32)
587 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
588 name, hModule );
589 _lclose32( hFile );
590 return hModule;
592 else /* module is already loaded, just create a new data segment if it's a task */
594 pModule = MODULE_GetPtr32( hModule );
595 hInstance = MODULE_CreateInstance( hModule, &hPrevInstance,
596 (cmd_line == NULL) );
597 if (hInstance != hPrevInstance) /* not a library */
598 NE_LoadSegment( pModule, pModule->dgroup );
599 pModule->count++;
601 } /* !winelib */
603 /* Create a task for this instance */
605 if (cmd_line && !(pModule->flags & NE_FFLAGS_LIBMODULE))
607 PDB32 *pdb;
609 pModule->flags |= NE_FFLAGS_GUI;
611 pdb = PROCESS_Create( pModule, cmd_line, env, hInstance,
612 hPrevInstance, show_cmd );
613 if (pdb && (GetNumTasks() > 1)) Yield16();
616 return hInstance;
620 /**********************************************************************
621 * LoadModule16 (KERNEL.45)
623 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
625 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
626 LPSTR cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
627 LPSTR new_cmd_line;
628 UINT16 show_cmd = 0;
629 LPCVOID env = NULL;
630 HINSTANCE16 hInstance;
632 if (!paramBlock || (paramBlock == (LPVOID)-1))
633 return LoadLibrary16( name );
635 params = (LOADPARAMS *)paramBlock;
636 cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
637 /* PowerPoint passes NULL as showCmd */
638 if (params->showCmd)
639 show_cmd = *((UINT16 *)PTR_SEG_TO_LIN(params->showCmd)+1);
641 if (!cmd_line) cmd_line = "";
642 else if (*cmd_line) cmd_line++; /* skip the length byte */
644 if (!(new_cmd_line = HeapAlloc( GetProcessHeap(), 0,
645 strlen(cmd_line) + strlen(name) + 2 )))
646 return 0;
647 strcpy( new_cmd_line, name );
648 strcat( new_cmd_line, " " );
649 strcat( new_cmd_line, cmd_line );
651 if (params->hEnvironment) env = GlobalLock16( params->hEnvironment );
652 hInstance = MODULE_Load( name, 0, new_cmd_line, env, show_cmd );
653 if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
654 HeapFree( GetProcessHeap(), 0, new_cmd_line );
655 return hInstance;
658 /**********************************************************************
659 * LoadModule32 (KERNEL32.499)
661 * FIXME
663 * This should get implemented via CreateProcess -- MODULE_Load
664 * is resolutely 16-bit.
666 DWORD LoadModule32( LPCSTR name, LPVOID paramBlock )
668 LOADPARAMS32 *params = (LOADPARAMS32 *)paramBlock;
669 #if 0
670 STARTUPINFO st;
671 PROCESSINFORMATION pi;
672 st.cb = sizeof(STARTUPINFO);
673 st.wShowWindow = p->lpCmdShow[2] ; WRONG
675 BOOL32 ret = CreateProcess32A( name, p->lpCmdLine,
676 NULL, NULL, FALSE, 0, p->lpEnvAddress,
677 NULL, &st, &pi);
678 if (!ret) {
679 /* handle errors appropriately */
681 CloseHandle32(pi.hProcess);
682 CloseHandle32(pi.hThread);
684 #else
685 return MODULE_Load( name, 0, params->lpCmdLine, params->lpEnvAddress,
686 *((UINT16 *)params->lpCmdShow + 1) );
687 #endif
691 /**********************************************************************
692 * FreeModule16 (KERNEL.46)
694 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
696 NE_MODULE *pModule;
698 if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
699 TRACE(module, "%s count %d\n",
700 MODULE_GetModuleName(hModule), pModule->count );
702 return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
706 /**********************************************************************
707 * GetModuleHandle16 (KERNEL.47)
709 HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
711 if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
712 return MODULE_FindModule16( PTR_SEG_TO_LIN(name) );
715 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
717 return MODULE_FindModule16( name );
720 /***********************************************************************
721 * GetModuleHandle (KERNEL32.237)
723 HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
726 TRACE(win32, "%s\n", module ? module : "NULL");
727 if (module == NULL)
728 return PROCESS_Current()->exe_modref->module;
729 else
730 return MODULE_FindModule32(PROCESS_Current(),module);
733 HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
735 HMODULE32 hModule;
736 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
737 hModule = GetModuleHandle32A( modulea );
738 HeapFree( GetProcessHeap(), 0, modulea );
739 return hModule;
743 /**********************************************************************
744 * GetModuleUsage (KERNEL.48)
746 INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
748 NE_MODULE *pModule;
750 if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
751 TRACE(module, "(%04x): returning %d\n",
752 hModule, pModule->count );
753 return pModule->count;
757 /**********************************************************************
758 * GetModuleFileName16 (KERNEL.49)
760 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
761 INT16 nSize )
763 NE_MODULE *pModule;
765 if (!hModule) hModule = GetCurrentTask();
766 if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
767 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
768 TRACE(module, "%s\n", lpFileName );
769 return strlen(lpFileName);
773 /***********************************************************************
774 * GetModuleFileName32A (KERNEL32.235)
775 * FIXME FIXME
777 DWORD WINAPI GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName,
778 DWORD size )
780 NE_MODULE *pModule;
782 if (!hModule)
784 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
785 hModule = pTask->hInstance;
787 if (!(pModule = MODULE_GetPtr32( hModule ))) return 0;
788 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
789 TRACE(module, "%s\n", lpFileName );
790 return strlen(lpFileName);
794 /***********************************************************************
795 * GetModuleFileName32W (KERNEL32.236)
797 DWORD WINAPI GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName,
798 DWORD size )
800 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
801 DWORD res = GetModuleFileName32A( hModule, fnA, size );
802 lstrcpynAtoW( lpFileName, fnA, size );
803 HeapFree( GetProcessHeap(), 0, fnA );
804 return res;
808 /**********************************************************************
809 * GetModuleName (KERNEL.27)
811 BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
813 LPSTR name = MODULE_GetModuleName(hinst);
815 if (!name) return FALSE;
816 lstrcpyn32A( buf, name, nSize );
817 return TRUE;
821 /***********************************************************************
822 * LoadLibraryEx32W (KERNEL.513)
823 * FIXME
825 HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
826 DWORD flags )
828 TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
829 return LoadLibraryEx32A(libname, hf,flags);
832 /***********************************************************************
833 * LoadLibraryEx32A (KERNEL32)
835 HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
837 HMODULE32 hmod;
839 hmod = PE_LoadLibraryEx32A(libname,PROCESS_Current(),hfile,flags);
840 if (hmod < 32) {
841 char buffer[256];
843 strcpy( buffer, libname );
844 strcat( buffer, ".dll" );
845 hmod = PE_LoadLibraryEx32A(buffer,PROCESS_Current(),hfile,flags);
847 /* initialize all DLLs, which haven't been initialized yet. */
848 if (hmod >= 32)
849 PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH, NULL);
850 return hmod;
853 /***********************************************************************
854 * LoadLibraryA (KERNEL32)
856 HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
857 return LoadLibraryEx32A(libname,0,0);
860 /***********************************************************************
861 * LoadLibraryW (KERNEL32)
863 HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
865 return LoadLibraryEx32W(libnameW,0,0);
868 /***********************************************************************
869 * LoadLibraryExW (KERNEL32)
871 HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
873 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
874 HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
876 HeapFree( GetProcessHeap(), 0, libnameA );
877 return ret;
880 /***********************************************************************
881 * FreeLibrary
883 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
885 TRACE(module,"hLibModule=%08x\n", hLibModule);
886 return MODULE_FreeModule(hLibModule,GlobalLock16(GetCurrentTask()) );
890 /***********************************************************************
891 * LoadLibrary (KERNEL.95)
893 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
895 HINSTANCE16 handle;
897 TRACE(module, "(%08x) %s\n", (int)libname, libname);
899 handle = MODULE_Load( libname, 0, NULL, NULL, 0 );
900 if (handle == (HINSTANCE16)2) /* file not found */
902 char buffer[256];
903 lstrcpyn32A( buffer, libname, 252 );
904 strcat( buffer, ".dll" );
905 handle = MODULE_Load( buffer, 0, NULL, NULL, 0 );
907 return handle;
911 /***********************************************************************
912 * PrivateLoadLibrary (KERNEL32)
914 * FIXME: rough guesswork, don't know what "Private" means
916 HINSTANCE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
918 return (HINSTANCE32)LoadLibrary16(libname);
922 /***********************************************************************
923 * FreeLibrary16 (KERNEL.96)
925 void WINAPI FreeLibrary16( HINSTANCE16 handle )
927 TRACE(module,"%04x\n", handle );
928 FreeModule16( handle );
932 /***********************************************************************
933 * PrivateFreeLibrary (KERNEL32)
935 * FIXME: rough guesswork, don't know what "Private" means
937 void WINAPI PrivateFreeLibrary(HINSTANCE32 handle)
939 FreeLibrary16((HINSTANCE16)handle);
943 /***********************************************************************
944 * WinExec16 (KERNEL.166)
946 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
948 return WinExec32( lpCmdLine, nCmdShow );
952 /***********************************************************************
953 * WinExec32 (KERNEL32.566)
955 HINSTANCE32 WINAPI WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
957 HINSTANCE32 handle = 2;
958 char *p, filename[256];
959 static int use_load_module = 1;
960 int spacelimit = 0, exhausted = 0;
962 if (!lpCmdLine)
963 return 2; /* File not found */
965 /* Keep trying to load a file by trying different filenames; e.g.,
966 for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
967 then "abcd efg" with arg "hij", and finally "abcd efg hij" with
968 no args */
970 while(!exhausted && handle == 2) {
971 int spacecount = 0;
973 /* Build the filename and command-line */
975 lstrcpyn32A(filename, lpCmdLine,
976 sizeof(filename) - 4 /* for extension */);
978 /* Keep grabbing characters until end-of-string, tab, or until the
979 number of spaces is greater than the spacelimit */
981 for (p = filename; ; p++) {
982 if(*p == ' ') {
983 ++spacecount;
984 if(spacecount > spacelimit) {
985 ++spacelimit;
986 break;
990 if(*p == '\0' || *p == '\t') {
991 exhausted = 1;
992 break;
996 *p = '\0';
998 /* Now load the executable file */
1000 if (use_load_module)
1002 /* Winelib: Use LoadModule() only for the program itself */
1003 if (__winelib) use_load_module = 0;
1004 handle = MODULE_Load( filename, 0, lpCmdLine, NULL, nCmdShow );
1005 if (handle == 2) /* file not found */
1007 /* Check that the original file name did not have a suffix */
1008 p = strrchr(filename, '.');
1009 /* if there is a '.', check if either \ OR / follow */
1010 if (!p || strchr(p, '/') || strchr(p, '\\'))
1012 p = filename + strlen(filename);
1013 strcpy( p, ".exe" );
1014 handle = MODULE_Load( filename, 0, lpCmdLine,
1015 NULL, nCmdShow );
1016 *p = '\0'; /* Remove extension */
1020 else
1021 handle = 2; /* file not found */
1023 if (handle < 32)
1025 /* Try to start it as a unix program */
1026 if (!fork())
1028 /* Child process */
1029 DOS_FULL_NAME full_name;
1030 const char *unixfilename = NULL;
1031 const char *argv[256], **argptr;
1032 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1033 nCmdShow == SW_SHOWMINNOACTIVE);
1035 THREAD_InitDone = FALSE; /* we didn't init this process */
1036 /* get unixfilename */
1037 if (strchr(filename, '/') ||
1038 strchr(filename, ':') ||
1039 strchr(filename, '\\'))
1041 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1042 unixfilename = full_name.long_name;
1044 else unixfilename = filename;
1046 if (unixfilename)
1048 /* build argv */
1049 argptr = argv;
1050 if (iconic) *argptr++ = "-iconic";
1051 *argptr++ = unixfilename;
1052 p = strdup(lpCmdLine);
1053 while (1)
1055 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1056 if (!*p) break;
1057 *argptr++ = p;
1058 while (*p && *p != ' ' && *p != '\t') p++;
1060 *argptr++ = 0;
1062 /* Execute */
1063 execvp(argv[0], (char**)argv);
1066 /* Failed ! */
1068 if (__winelib)
1070 /* build argv */
1071 argptr = argv;
1072 *argptr++ = "wine";
1073 if (iconic) *argptr++ = "-iconic";
1074 *argptr++ = lpCmdLine;
1075 *argptr++ = 0;
1077 /* Execute */
1078 execvp(argv[0] , (char**)argv);
1080 /* Failed ! */
1081 MSG("WinExec: can't exec 'wine %s'\n",
1082 lpCmdLine);
1084 exit(1);
1087 } /* while (!exhausted && handle < 32) */
1089 return handle;
1093 /***********************************************************************
1094 * WIN32_GetProcAddress16 (KERNEL32.36)
1095 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1097 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
1099 WORD ordinal;
1100 FARPROC16 ret;
1102 if (!hModule) {
1103 WARN(module,"hModule may not be 0!\n");
1104 return (FARPROC16)0;
1106 hModule = MODULE_HANDLEtoHMODULE16(hModule);
1107 if (HIWORD(name)) {
1108 ordinal = NE_GetOrdinal( hModule, name );
1109 TRACE(module, "%04x '%s'\n",
1110 hModule, name );
1111 } else {
1112 ordinal = LOWORD(name);
1113 TRACE(module, "%04x %04x\n",
1114 hModule, ordinal );
1116 if (!ordinal) return (FARPROC16)0;
1117 ret = NE_GetEntryPoint( hModule, ordinal );
1118 TRACE(module,"returning %08x\n",(UINT32)ret);
1119 return ret;
1122 /***********************************************************************
1123 * GetProcAddress16 (KERNEL.50)
1125 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1127 WORD ordinal;
1128 FARPROC16 ret;
1130 if (!hModule) hModule = GetCurrentTask();
1131 hModule = GetExePtr( hModule );
1133 if (HIWORD(name) != 0)
1135 ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1136 TRACE(module, "%04x '%s'\n",
1137 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1139 else
1141 ordinal = LOWORD(name);
1142 TRACE(module, "%04x %04x\n",
1143 hModule, ordinal );
1145 if (!ordinal) return (FARPROC16)0;
1147 ret = NE_GetEntryPoint( hModule, ordinal );
1149 TRACE(module, "returning %08x\n", (UINT32)ret );
1150 return ret;
1154 /***********************************************************************
1155 * GetProcAddress32 (KERNEL32.257)
1157 FARPROC32 WINAPI GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1159 return MODULE_GetProcAddress32( PROCESS_Current(), hModule, function );
1163 /***********************************************************************
1164 * MODULE_GetProcAddress32 (internal)
1166 FARPROC32 MODULE_GetProcAddress32(
1167 PDB32 *process, /* [in] process context */
1168 HMODULE32 hModule, /* [in] current module handle */
1169 LPCSTR function ) /* [in] function to be looked up */
1171 WINE_MODREF *wm = MODULE32_LookupHMODULE(process,hModule);
1173 if (HIWORD(function))
1174 TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1175 else
1176 TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1177 if (!wm)
1178 return (FARPROC32)0;
1179 switch (wm->type)
1181 case MODULE32_PE:
1182 return PE_FindExportedFunction( process, wm, function);
1183 default:
1184 ERR(module,"wine_modref type %d not handled.\n",wm->type);
1185 return (FARPROC32)0;
1190 /***********************************************************************
1191 * RtlImageNtHeaders (NTDLL)
1193 LPIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
1195 /* basically:
1196 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1197 * but we could get HMODULE16 or the like (think builtin modules)
1200 WINE_MODREF *wm = MODULE32_LookupHMODULE( PROCESS_Current(), hModule );
1201 if (!wm || (wm->type != MODULE32_PE)) return (LPIMAGE_NT_HEADERS)0;
1202 return PE_HEADER(wm->module);
1206 /**********************************************************************
1207 * GetExpWinVer (KERNEL.167)
1209 WORD WINAPI GetExpWinVer( HMODULE16 hModule )
1211 NE_MODULE *pModule = MODULE_GetPtr16( hModule );
1212 return pModule ? pModule->expected_version : 0;
1216 /**********************************************************************
1217 * IsSharedSelector (KERNEL.345)
1219 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
1221 /* Check whether the selector belongs to a DLL */
1222 NE_MODULE *pModule = MODULE_GetPtr16( selector );
1223 if (!pModule) return FALSE;
1224 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1228 /**********************************************************************
1229 * ModuleFirst (TOOLHELP.59)
1231 BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
1233 lpme->wNext = hFirstModule;
1234 return ModuleNext( lpme );
1238 /**********************************************************************
1239 * ModuleNext (TOOLHELP.60)
1241 BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
1243 NE_MODULE *pModule;
1244 char *name;
1246 if (!lpme->wNext) return FALSE;
1247 if (!(pModule = MODULE_GetPtr16( lpme->wNext ))) return FALSE;
1248 name = (char *)pModule + pModule->name_table;
1249 memcpy( lpme->szModule, name + 1, *name );
1250 lpme->szModule[(BYTE)*name] = '\0';
1251 lpme->hModule = lpme->wNext;
1252 lpme->wcUsage = pModule->count;
1253 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1254 lpme->szExePath[MAX_PATH] = '\0';
1255 lpme->wNext = pModule->next;
1256 return TRUE;
1260 /**********************************************************************
1261 * ModuleFindName (TOOLHELP.61)
1263 BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1265 lpme->wNext = GetModuleHandle16( name );
1266 return ModuleNext( lpme );
1270 /**********************************************************************
1271 * ModuleFindHandle (TOOLHELP.62)
1273 BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1275 hModule = GetExePtr( hModule );
1276 lpme->wNext = hModule;
1277 return ModuleNext( lpme );