Fix the case of product and company names.
[wine] / loader / ne / module.c
1 /*
2  * NE modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <ctype.h>
34
35 #include "windef.h"
36 #include "winbase.h"
37 #include "wine/winbase16.h"
38 #include "wine/library.h"
39 #include "winerror.h"
40 #include "module.h"
41 #include "toolhelp.h"
42 #include "file.h"
43 #include "task.h"
44 #include "snoop.h"
45 #include "builtin16.h"
46 #include "stackframe.h"
47 #include "excpt.h"
48 #include "wine/exception.h"
49 #include "wine/debug.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(module);
52 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
53
54 #include "pshpack1.h"
55 typedef struct _GPHANDLERDEF
56 {
57     WORD selector;
58     WORD rangeStart;
59     WORD rangeEnd;
60     WORD handler;
61 } GPHANDLERDEF;
62 #include "poppack.h"
63
64 #define hFirstModule (pThhook->hExeHead)
65
66
67 /***********************************************************************
68  *           NE_GetPtr
69  */
70 NE_MODULE *NE_GetPtr( HMODULE16 hModule )
71 {
72     return (NE_MODULE *)GlobalLock16( GetExePtr(hModule) );
73 }
74
75
76 /**********************************************************************
77  *          GetModuleFileName      (KERNEL.49)
78  *
79  * Comment: see GetModuleFileNameA
80  *
81  * Even if invoked by second instance of a program,
82  * it still returns path of first one.
83  */
84 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
85                                   INT16 nSize )
86 {
87     NE_MODULE *pModule;
88
89     /* Win95 does not query hModule if set to 0 !
90      * Is this wrong or maybe Win3.1 only ? */
91     if (!hModule) hModule = GetCurrentTask();
92
93     if (!(pModule = NE_GetPtr( hModule ))) return 0;
94     lstrcpynA( lpFileName, NE_MODULE_NAME(pModule), nSize );
95     if (pModule->expected_version >= 0x400)
96         GetLongPathNameA(NE_MODULE_NAME(pModule), lpFileName, nSize);
97     TRACE("%04x -> '%s'\n", hModule, lpFileName );
98     return strlen(lpFileName);
99 }
100
101
102 /***********************************************************************
103  *          GetModuleHandle16 (KERNEL32.@)
104  */
105 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
106 {
107     HMODULE16   hModule = hFirstModule;
108     LPSTR       s;
109     BYTE        len, *name_table;
110     char        tmpstr[MAX_PATH];
111     NE_MODULE *pModule;
112
113     TRACE("(%s)\n", name);
114
115     if (!HIWORD(name))
116         return GetExePtr(LOWORD(name));
117
118     len = strlen(name);
119     if (!len)
120         return 0;
121
122     lstrcpynA(tmpstr, name, sizeof(tmpstr));
123
124     /* If 'name' matches exactly the module name of a module:
125      * Return its handle.
126      */
127     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
128     {
129         pModule = NE_GetPtr( hModule );
130         if (!pModule) break;
131         if (pModule->flags & NE_FFLAGS_WIN32) continue;
132
133         name_table = (BYTE *)pModule + pModule->name_table;
134         if ((*name_table == len) && !strncmp(name, name_table+1, len))
135             return hModule;
136     }
137
138     /* If uppercased 'name' matches exactly the module name of a module:
139      * Return its handle
140      */
141     for (s = tmpstr; *s; s++) *s = FILE_toupper(*s);
142
143     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
144     {
145         pModule = NE_GetPtr( hModule );
146         if (!pModule) break;
147         if (pModule->flags & NE_FFLAGS_WIN32) continue;
148
149         name_table = (BYTE *)pModule + pModule->name_table;
150         /* FIXME: the strncasecmp is WRONG. It should not be case insensitive,
151          * but case sensitive! (Unfortunately Winword 6 and subdlls have
152          * lowercased module names, but try to load uppercase DLLs, so this
153          * 'i' compare is just a quickfix until the loader handles that
154          * correctly. -MM 990705
155          */
156         if ((*name_table == len) && !FILE_strncasecmp(tmpstr, name_table+1, len))
157             return hModule;
158     }
159
160     /* If the base filename of 'name' matches the base filename of the module
161      * filename of some module (case-insensitive compare):
162      * Return its handle.
163      */
164
165     /* basename: search backwards in passed name to \ / or : */
166     s = tmpstr + strlen(tmpstr);
167     while (s > tmpstr)
168     {
169         if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
170                 break;
171         s--;
172     }
173
174     /* search this in loaded filename list */
175     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
176     {
177         char            *loadedfn;
178         OFSTRUCT        *ofs;
179
180         pModule = NE_GetPtr( hModule );
181         if (!pModule) break;
182         if (!pModule->fileinfo) continue;
183         if (pModule->flags & NE_FFLAGS_WIN32) continue;
184
185         ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
186         loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
187         /* basename: search backwards in pathname to \ / or : */
188         while (loadedfn > (char*)ofs->szPathName)
189         {
190             if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
191                     break;
192             loadedfn--;
193         }
194         /* case insensitive compare ... */
195         if (!FILE_strcasecmp(loadedfn, s))
196             return hModule;
197     }
198     return 0;
199 }