1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/mslu.cpp
3 // Purpose:     Fixes for bugs in MSLU
4 // Author:      Vaclav Slavik
5 // Modified by:
6 // Created:     2002/02/17
7 // Copyright:   (c) 2002 Vaclav Slavik
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13 
14 #ifdef __BORLANDC__
15     #pragma hdrstop
16     #include <dir.h>
17 #endif
18 
19 #ifndef WX_PRECOMP
20     #include "wx/utils.h"
21 #endif
22 
23 #define wxHAS_HUGE_FILES
24 
25 //------------------------------------------------------------------------
26 // Check for use of MSLU
27 //------------------------------------------------------------------------
28 
29 #if wxUSE_BASE
30 
wxUsingUnicowsDll()31 bool WXDLLIMPEXP_BASE wxUsingUnicowsDll()
32 {
33 #if wxUSE_UNICODE_MSLU
34     return (wxGetOsVersion() == wxOS_WINDOWS_9X);
35 #else
36     return false;
37 #endif
38 }
39 
40 #endif // wxUSE_BASE
41 
42 
43 #if wxUSE_UNICODE_MSLU
44 
45 //------------------------------------------------------------------------
46 //
47 // NB: MSLU only covers Win32 API, it doesn't provide Unicode implementation of
48 //     libc functions. Unfortunately, some of MSVCRT wchar_t functions
49 //     (e.g. _wopen) don't work on Windows 9x, so we have to workaround it
50 //     by calling the char version. We still want to use wchar_t version on
51 //     NT/2000/XP, though, because they allow for Unicode file names.
52 //
53 //     Moreover, there are bugs in unicows.dll, of course. We have to
54 //     workaround them, too.
55 //
56 //------------------------------------------------------------------------
57 
58 #include "wx/msw/private.h"
59 #include "wx/msw/mslu.h"
60 
61 #include <stdio.h>
62 #include <io.h>
63 #include <sys/stat.h>
64 
65 #ifdef __VISUALC__
66     #include <direct.h>
67 #endif
68 
69 // Undef redirection macros defined in wx/msw/wrapwin.h:
70 #undef DrawStateW
71 #undef GetOpenFileNameW
72 #undef GetSaveFileNameW
73 
74 //------------------------------------------------------------------------
75 // Wrongly implemented functions from unicows.dll
76 //------------------------------------------------------------------------
77 
78 #if wxUSE_GUI
79 
wxMSLU_DrawStateW(WXHDC dc,WXHBRUSH br,WXFARPROC outputFunc,WXLPARAM lData,WXWPARAM wData,int x,int y,int cx,int cy,unsigned int flags)80 WXDLLEXPORT int  wxMSLU_DrawStateW(WXHDC dc, WXHBRUSH br, WXFARPROC outputFunc,
81                                    WXLPARAM lData, WXWPARAM wData,
82                                    int x, int y, int cx, int cy,
83                                    unsigned int flags)
84 {
85     // VS: There's yet another bug in MSLU: DrawStateW behaves like if it was
86     //     expecting char*, not wchar_t* input. We have to use DrawStateA
87     //     explicitly.
88 
89     if ( wxUsingUnicowsDll() )
90     {
91         return DrawStateA((HDC)dc, (HBRUSH)br, (DRAWSTATEPROC)outputFunc,
92                           (LPARAM)(const char*)
93                                 wxConvLocal.cWX2MB((const wxChar*)lData),
94                           wData, x, y, cx, cy, flags);
95     }
96     else
97     {
98         return DrawStateW((HDC)dc, (HBRUSH)br, (DRAWSTATEPROC)outputFunc,
99                           lData, wData, x, y, cx, cy, flags);
100     }
101 }
102 
wxFixOPENFILENAME(LPOPENFILENAME ofn)103 static void wxFixOPENFILENAME(LPOPENFILENAME ofn)
104 {
105 #ifdef OFN_EXPLORER
106     // VS: there's a bug in unicows.dll - when multiple files are selected,
107     //     of.nFileOffset doesn't point to the first filename but rather to
108     //     the last component of directory name. This bug is known to MSLU
109     //     developers, but they are not going to fix it: "this is a true
110     //     limitation, that we have decided to live with" and "working
111     //     harder on this case just did not seem worth the effort"...
112     //
113     //     Our only option is to try to fix it ourselves:
114 
115     if ( (ofn->Flags & OFN_ALLOWMULTISELECT) &&
116          ofn->lpstrFile[ofn->nFileOffset-1] != wxT('\0') )
117     {
118         if ( wxDirExists(ofn->lpstrFile) )
119         {
120             // 1st component is dir => multiple files selected
121             ofn->nFileOffset = wxStrlen(ofn->lpstrFile)+1;
122         }
123     }
124 #endif // OFN_EXPLORER
125 }
126 
wxMSLU_GetOpenFileNameW(void * ofn)127 WXDLLEXPORT int wxMSLU_GetOpenFileNameW(void *ofn)
128 {
129     int ret = GetOpenFileName((LPOPENFILENAME)ofn);
130     if ( wxUsingUnicowsDll() && ret != 0 )
131         wxFixOPENFILENAME((LPOPENFILENAME)ofn);
132     return ret;
133 }
134 
wxMSLU_GetSaveFileNameW(void * ofn)135 WXDLLEXPORT int wxMSLU_GetSaveFileNameW(void *ofn)
136 {
137     int ret = GetSaveFileName((LPOPENFILENAME)ofn);
138     if ( wxUsingUnicowsDll() && ret != 0 )
139         wxFixOPENFILENAME((LPOPENFILENAME)ofn);
140     return ret;
141 }
142 
143 #endif // wxUSE_GUI
144 
145 //------------------------------------------------------------------------
146 // Missing libc file manipulation functions in Win9x
147 //------------------------------------------------------------------------
148 
149 #if wxUSE_BASE
150 
wxMSLU__wrename(const wchar_t * oldname,const wchar_t * newname)151 WXDLLIMPEXP_BASE int wxMSLU__wrename(const wchar_t *oldname,
152                                      const wchar_t *newname)
153 {
154     if ( wxUsingUnicowsDll() )
155         return rename(wxConvFile.cWX2MB(oldname), wxConvFile.cWX2MB(newname));
156     else
157         return _wrename(oldname, newname);
158 }
159 
wxMSLU__wremove(const wchar_t * name)160 WXDLLIMPEXP_BASE int wxMSLU__wremove(const wchar_t *name)
161 {
162     if ( wxUsingUnicowsDll() )
163         return remove(wxConvFile.cWX2MB(name));
164     else
165         return _wremove(name);
166 }
167 
wxMSLU__wfopen(const wchar_t * name,const wchar_t * mode)168 WXDLLIMPEXP_BASE FILE* wxMSLU__wfopen(const wchar_t *name,const wchar_t* mode)
169 {
170     if ( wxUsingUnicowsDll() )
171         return fopen(wxConvFile.cWX2MB(name),wxConvFile.cWX2MB(mode));
172     else
173         return _wfopen(name,mode);
174 }
175 
wxMSLU__wfreopen(const wchar_t * name,const wchar_t * mode,FILE * stream)176 WXDLLIMPEXP_BASE FILE* wxMSLU__wfreopen(const wchar_t *name,
177                                         const wchar_t* mode,
178                                         FILE *stream)
179 {
180     if ( wxUsingUnicowsDll() )
181         return freopen(wxConvFile.cWX2MB(name), wxConvFile.cWX2MB(mode), stream);
182     else
183         return _wfreopen(name, mode, stream);
184 }
185 
wxMSLU__wopen(const wchar_t * name,int flags,int mode)186 WXDLLIMPEXP_BASE int wxMSLU__wopen(const wchar_t *name, int flags, int mode)
187 {
188     if ( wxUsingUnicowsDll() )
189         return wxCRT_OpenA(wxConvFile.cWX2MB(name), flags, mode);
190     else
191         return wxCRT_OpenW(name, flags, mode);
192 }
193 
wxMSLU__waccess(const wchar_t * name,int mode)194 WXDLLIMPEXP_BASE int wxMSLU__waccess(const wchar_t *name, int mode)
195 {
196     if ( wxUsingUnicowsDll() )
197         return wxCRT_AccessA(wxConvFile.cWX2MB(name), mode);
198     else
199         return wxCRT_AccessW(name, mode);
200 }
201 
wxMSLU__wchmod(const wchar_t * name,int mode)202 WXDLLIMPEXP_BASE int wxMSLU__wchmod(const wchar_t *name, int mode)
203 {
204     if ( wxUsingUnicowsDll() )
205         return wxCRT_ChmodA(wxConvFile.cWX2MB(name), mode);
206     else
207         return wxCRT_ChmodW(name, mode);
208 }
209 
wxMSLU__wmkdir(const wchar_t * name)210 WXDLLIMPEXP_BASE int wxMSLU__wmkdir(const wchar_t *name)
211 {
212     if ( wxUsingUnicowsDll() )
213         return wxCRT_MkDirA(wxConvFile.cWX2MB(name));
214     else
215         return wxCRT_MkDirW(name);
216 }
217 
wxMSLU__wrmdir(const wchar_t * name)218 WXDLLIMPEXP_BASE int wxMSLU__wrmdir(const wchar_t *name)
219 {
220     if ( wxUsingUnicowsDll() )
221         return wxCRT_RmDirA(wxConvFile.cWX2MB(name));
222     else
223         return wxCRT_RmDirW(name);
224 }
225 
wxMSLU__wstat(const wchar_t * name,wxStructStat * buffer)226 WXDLLIMPEXP_BASE int wxMSLU__wstat(const wchar_t *name, wxStructStat *buffer)
227 {
228     if ( wxUsingUnicowsDll() )
229         return wxCRT_StatA((const char*)wxConvFile.cWX2MB(name), buffer);
230     else
231         return wxCRT_StatW(name, buffer);
232 }
233 
234 #endif // wxUSE_BASE
235 
236 #endif // wxUSE_UNICODE_MSLU
237