blob: 933f348b44d9733dac3670e175ae9db7e9a24445 [file] [log] [blame]
Alexandre Julliard58199531994-04-21 01:20:00 +00001/*
2 * Shell Library Functions
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00003 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00004 * 1998 Marcus Meissner
Alexandre Julliard58199531994-04-21 01:20:00 +00005 */
Alexandre Julliarde658d821997-11-30 17:45:40 +00006#include <assert.h>
Alexandre Julliard58199531994-04-21 01:20:00 +00007#include <stdlib.h>
Alexandre Julliard58199531994-04-21 01:20:00 +00008#include <string.h>
9#include <unistd.h>
Alexandre Julliard808cb041995-08-17 17:11:36 +000010#include <ctype.h>
Michael Vekslerca1bc861999-01-01 18:57:33 +000011#include "wine/winuser16.h"
Marcus Meissner317af321999-02-17 13:51:06 +000012#include "wine/winbase16.h"
13#include "wine/shell16.h"
Alexandre Julliard44ed71f1997-12-21 19:17:50 +000014#include "winerror.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000015#include "file.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000016#include "heap.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000017#include "module.h"
Alexandre Julliard7cbe6571995-01-09 18:21:16 +000018#include "neexe.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000019#include "dlgs.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000020#include "win.h"
Alexandre Julliard1e37a181996-08-18 16:21:52 +000021#include "cursoricon.h"
Alexandre Julliarde658d821997-11-30 17:45:40 +000022#include "sysmetrics.h"
Marcus Meissner317af321999-02-17 13:51:06 +000023#include "shellapi.h"
Alexandre Julliarde658d821997-11-30 17:45:40 +000024#include "shlobj.h"
Alexandre Julliard3a405ba1994-10-30 16:25:19 +000025#include "debug.h"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000026#include "winreg.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000027#include "imagelist.h"
Alexandre Julliard58199531994-04-21 01:20:00 +000028
Alexandre Julliard1e37a181996-08-18 16:21:52 +000029/* .ICO file ICONDIR definitions */
30
31#pragma pack(1)
32
33typedef struct
34{
35 BYTE bWidth; /* Width, in pixels, of the image */
36 BYTE bHeight; /* Height, in pixels, of the image */
37 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
38 BYTE bReserved; /* Reserved ( must be 0) */
39 WORD wPlanes; /* Color Planes */
40 WORD wBitCount; /* Bits per pixel */
41 DWORD dwBytesInRes; /* How many bytes in this resource? */
42 DWORD dwImageOffset; /* Where in the file is this image? */
43} icoICONDIRENTRY, *LPicoICONDIRENTRY;
44
45typedef struct
46{
47 WORD idReserved; /* Reserved (must be 0) */
48 WORD idType; /* Resource Type (1 for icons) */
49 WORD idCount; /* How many images? */
50 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
51} icoICONDIR, *LPicoICONDIR;
52
53#pragma pack(4)
54
Alexandre Julliard889f7421997-04-15 17:19:52 +000055static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
56static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
57static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
58
59static HWND16 SHELL_hWnd = 0;
60static HHOOK SHELL_hHook = 0;
61static UINT16 uMsgWndCreated = 0;
62static UINT16 uMsgWndDestroyed = 0;
63static UINT16 uMsgShellActivate = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000064
Alexandre Julliardd18872d1994-05-11 12:18:19 +000065/*************************************************************************
Kai Morich0913cdf1998-10-24 12:02:54 +000066 * DragAcceptFiles32 [SHELL32.54]
Alexandre Julliardd18872d1994-05-11 12:18:19 +000067 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000068void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
Kai Morich0913cdf1998-10-24 12:02:54 +000069{
70 WND* wnd = WIN_FindWndPtr(hWnd);
71
72 if( wnd )
73 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
74 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
Alexandre Julliardd18872d1994-05-11 12:18:19 +000075}
76
Kai Morich0913cdf1998-10-24 12:02:54 +000077/*************************************************************************
78 * DragAcceptFiles16 [SHELL.9]
79 */
80void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b)
81{
Alexandre Julliarda3960291999-02-26 11:11:13 +000082 DragAcceptFiles(hWnd, b);
Kai Morich0913cdf1998-10-24 12:02:54 +000083}
Alexandre Julliardd18872d1994-05-11 12:18:19 +000084
85/*************************************************************************
Kai Morich0913cdf1998-10-24 12:02:54 +000086 * SHELL_DragQueryFile [internal]
87 *
Alexandre Julliardd18872d1994-05-11 12:18:19 +000088 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000089static UINT SHELL_DragQueryFile(LPSTR lpDrop, LPWSTR lpwDrop, UINT lFile,
90 LPSTR lpszFile, LPWSTR lpszwFile, UINT lLength)
Kai Morich0913cdf1998-10-24 12:02:54 +000091{
Alexandre Julliarda3960291999-02-26 11:11:13 +000092 UINT i;
Kai Morich0913cdf1998-10-24 12:02:54 +000093
94 i = 0;
95 if (lpDrop) {
96 while (i++ < lFile) {
97 while (*lpDrop++); /* skip filename */
98 if (!*lpDrop)
99 return (lFile == 0xFFFFFFFF) ? i : 0;
100 }
101 }
102 if (lpwDrop) {
103 while (i++ < lFile) {
104 while (*lpwDrop++); /* skip filename */
105 if (!*lpwDrop)
106 return (lFile == 0xFFFFFFFF) ? i : 0;
107 }
108 }
109
Alexandre Julliarda3960291999-02-26 11:11:13 +0000110 if (lpDrop) i = lstrlenA(lpDrop);
111 if (lpwDrop) i = lstrlenW(lpwDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000112 i++;
113 if (!lpszFile && !lpszwFile) {
114 return i; /* needed buffer size */
115 }
116 i = (lLength > i) ? i : lLength;
117 if (lpszFile) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000118 if (lpDrop) lstrcpynA (lpszFile, lpDrop, i);
Kai Morich0913cdf1998-10-24 12:02:54 +0000119 else lstrcpynWtoA(lpszFile, lpwDrop, i);
120 } else {
121 if (lpDrop) lstrcpynAtoW(lpszwFile, lpDrop, i);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000122 else lstrcpynW (lpszwFile, lpwDrop, i);
Kai Morich0913cdf1998-10-24 12:02:54 +0000123 }
124 return i;
125}
126
127/*************************************************************************
128 * DragQueryFile32A [SHELL32.81] [shell32.82]
129 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000130UINT WINAPI DragQueryFileA(HDROP hDrop, UINT lFile, LPSTR lpszFile,
131 UINT lLength)
Kai Morich0913cdf1998-10-24 12:02:54 +0000132{ /* hDrop is a global memory block allocated with GMEM_SHARE
133 * with DROPFILESTRUCT as a header and filenames following
134 * it, zero length filename is in the end */
135
Alexandre Julliarda3960291999-02-26 11:11:13 +0000136 LPDROPFILESTRUCT lpDropFileStruct;
Kai Morich0913cdf1998-10-24 12:02:54 +0000137 LPSTR lpCurrent;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000138 UINT i;
Kai Morich0913cdf1998-10-24 12:02:54 +0000139
140 TRACE(shell,"(%08x, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
141
Alexandre Julliarda3960291999-02-26 11:11:13 +0000142 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000143 if(!lpDropFileStruct)
144 return 0;
145
146 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->lSize;
147 i = SHELL_DragQueryFile(lpCurrent, NULL, lFile, lpszFile, NULL, lLength);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000148 GlobalUnlock(hDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000149 return i;
150}
151
152/*************************************************************************
153 * DragQueryFile32W [shell32.133]
154 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000155UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile,
156 UINT lLength)
Kai Morich0913cdf1998-10-24 12:02:54 +0000157{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000158 LPDROPFILESTRUCT lpDropFileStruct;
Kai Morich0913cdf1998-10-24 12:02:54 +0000159 LPWSTR lpwCurrent;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000160 UINT i;
Kai Morich0913cdf1998-10-24 12:02:54 +0000161
162 TRACE(shell,"(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
163
Alexandre Julliarda3960291999-02-26 11:11:13 +0000164 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000165 if(!lpDropFileStruct)
166 return 0;
167
168 lpwCurrent = (LPWSTR) lpDropFileStruct + lpDropFileStruct->lSize;
169 i = SHELL_DragQueryFile(NULL, lpwCurrent, lFile, NULL, lpszwFile,lLength);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000170 GlobalUnlock(hDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000171 return i;
172}
173/*************************************************************************
174 * DragQueryFile16 [SHELL.11]
175 */
176UINT16 WINAPI DragQueryFile16(HDROP16 hDrop, WORD wFile, LPSTR lpszFile,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000177 WORD wLength)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000178{ /* hDrop is a global memory block allocated with GMEM_SHARE
Alexandre Julliardd4719651995-12-12 18:49:11 +0000179 * with DROPFILESTRUCT as a header and filenames following
180 * it, zero length filename is in the end */
181
Kai Morich0913cdf1998-10-24 12:02:54 +0000182 LPDROPFILESTRUCT16 lpDropFileStruct;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000183 LPSTR lpCurrent;
184 WORD i;
185
Kai Morich0913cdf1998-10-24 12:02:54 +0000186 TRACE(shell,"(%04x, %x, %p, %u)\n", hDrop,wFile,lpszFile,wLength);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000187
Kai Morich0913cdf1998-10-24 12:02:54 +0000188 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop);
189 if(!lpDropFileStruct)
190 return 0;
191
Alexandre Julliardd4719651995-12-12 18:49:11 +0000192 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000193
Kai Morich0913cdf1998-10-24 12:02:54 +0000194 i = (WORD)SHELL_DragQueryFile(lpCurrent, NULL, wFile==0xffff?0xffffffff:wFile,
195 lpszFile, NULL, wLength);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000196 GlobalUnlock16(hDrop);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000197 return i;
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000198}
199
200
Kai Morich0913cdf1998-10-24 12:02:54 +0000201
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000202/*************************************************************************
Kai Morich0913cdf1998-10-24 12:02:54 +0000203 * DragFinish32 [SHELL32.80]
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000204 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000205void WINAPI DragFinish(HDROP h)
Kai Morich0913cdf1998-10-24 12:02:54 +0000206{ TRACE(shell,"\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +0000207 GlobalFree((HGLOBAL)h);
Kai Morich0913cdf1998-10-24 12:02:54 +0000208}
209
210/*************************************************************************
211 * DragFinish16 [SHELL.12]
212 */
213void WINAPI DragFinish16(HDROP16 h)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000214{ TRACE(shell,"\n");
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000215 GlobalFree16((HGLOBAL16)h);
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000216}
217
218
219/*************************************************************************
Kai Morich0913cdf1998-10-24 12:02:54 +0000220 * DragQueryPoint32 [SHELL32.135]
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000221 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000222BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
Kai Morich0913cdf1998-10-24 12:02:54 +0000223{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000224 LPDROPFILESTRUCT lpDropFileStruct;
225 BOOL bRet;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000226 TRACE(shell,"\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +0000227 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000228
Alexandre Julliarda3960291999-02-26 11:11:13 +0000229 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT));
Kai Morich0913cdf1998-10-24 12:02:54 +0000230 bRet = lpDropFileStruct->fInNonClientArea;
231
Alexandre Julliarda3960291999-02-26 11:11:13 +0000232 GlobalUnlock(hDrop);
Kai Morich0913cdf1998-10-24 12:02:54 +0000233 return bRet;
234}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000235
Kai Morich0913cdf1998-10-24 12:02:54 +0000236/*************************************************************************
237 * DragQueryPoint16 [SHELL.13]
238 */
239BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p)
240{
241 LPDROPFILESTRUCT16 lpDropFileStruct;
242 BOOL16 bRet;
243 TRACE(shell,"\n");
244 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop);
245
246 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
247 bRet = lpDropFileStruct->fInNonClientArea;
248
249 GlobalUnlock16(hDrop);
250 return bRet;
Alexandre Julliard58199531994-04-21 01:20:00 +0000251}
252
Alexandre Julliard58199531994-04-21 01:20:00 +0000253/*************************************************************************
Alexandre Julliarda845b881998-06-01 10:44:35 +0000254 * SHELL_FindExecutable [Internal]
255 *
Alexandre Julliardef702d81996-05-28 18:54:58 +0000256 * Utility for code sharing between FindExecutable and ShellExecute
Alexandre Julliard58199531994-04-21 01:20:00 +0000257 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000258HINSTANCE SHELL_FindExecutable( LPCSTR lpFile,
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000259 LPCSTR lpOperation,
260 LPSTR lpResult)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000261{ char *extension = NULL; /* pointer to file extension */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000262 char tmpext[5]; /* local copy to mung as we please */
263 char filetype[256]; /* registry name for this filetype */
264 LONG filetypelen=256; /* length of above */
265 char command[256]; /* command from registry */
266 LONG commandlen=256; /* This is the most DOS can handle :) */
267 char buffer[256]; /* Used to GetProfileString */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000268 HINSTANCE retval=31; /* default - 'No association was found' */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000269 char *tok; /* token pointer */
270 int i; /* random counter */
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000271 char xlpFile[256]; /* result of SearchPath */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000272
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000273 TRACE(shell, "%s\n", (lpFile != NULL?lpFile:"-") );
Alexandre Julliarda845b881998-06-01 10:44:35 +0000274
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000275 lpResult[0]='\0'; /* Start off with an empty return string */
276
277 /* trap NULL parameters on entry */
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000278 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000279 { WARN(exec, "(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +0000280 lpFile, lpOperation, lpResult);
281 return 2; /* File not found. Close enough, I guess. */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000282 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000283
Alexandre Julliarda3960291999-02-26 11:11:13 +0000284 if (SearchPathA( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000285 { TRACE(shell, "SearchPath32A returned non-zero\n");
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000286 lpFile = xlpFile;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000287 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000288
289 /* First thing we need is the file's extension */
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000290 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
Alexandre Julliardca22b331996-07-12 19:02:39 +0000291 /* File->Run in progman uses */
292 /* .\FILE.EXE :( */
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000293 TRACE(shell, "xlpFile=%s,extension=%s\n", xlpFile, extension);
Alexandre Julliarda845b881998-06-01 10:44:35 +0000294
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000295 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000296 { WARN(shell, "Returning 31 - No association\n");
Alexandre Julliarda845b881998-06-01 10:44:35 +0000297 return 31; /* no association */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000298 }
299
300 /* Make local copy & lowercase it for reg & 'programs=' lookup */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000301 lstrcpynA( tmpext, extension, 5 );
302 CharLowerA( tmpext );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000303 TRACE(shell, "%s file\n", tmpext);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000304
305 /* Three places to check: */
306 /* 1. win.ini, [windows], programs (NB no leading '.') */
307 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
308 /* 3. win.ini, [extensions], extension (NB no leading '.' */
309 /* All I know of the order is that registry is checked before */
310 /* extensions; however, it'd make sense to check the programs */
311 /* section first, so that's what happens here. */
312
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000313 /* See if it's a program - if GetProfileString fails, we skip this
314 * section. Actually, if GetProfileString fails, we've probably
315 * got a lot more to worry about than running a program... */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000316 if ( GetProfileStringA("windows", "programs", "exe pif bat com",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000317 buffer, sizeof(buffer)) > 0 )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000318 { for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000319
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000320 tok = strtok(buffer, " \t"); /* ? */
321 while( tok!= NULL)
322 {
323 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
324 {
325 strcpy(lpResult, xlpFile);
326 /* Need to perhaps check that the file has a path
327 * attached */
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000328 TRACE(shell, "found %s\n", lpResult);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000329 return 33;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000330
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000331 /* Greater than 32 to indicate success FIXME According to the
332 * docs, I should be returning a handle for the
333 * executable. Does this mean I'm supposed to open the
334 * executable file or something? More RTFM, I guess... */
335 }
336 tok=strtok(NULL, " \t");
337 }
338 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000339
340 /* Check registry */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000341 if (RegQueryValue16( HKEY_CLASSES_ROOT, tmpext, filetype,
342 &filetypelen ) == ERROR_SUCCESS )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000343 {
344 filetype[filetypelen]='\0';
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000345 TRACE(shell, "File type: %s\n", filetype);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000346
Alexandre Julliardef702d81996-05-28 18:54:58 +0000347 /* Looking for ...buffer\shell\lpOperation\command */
348 strcat( filetype, "\\shell\\" );
349 strcat( filetype, lpOperation );
350 strcat( filetype, "\\command" );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000351
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000352 if (RegQueryValue16( HKEY_CLASSES_ROOT, filetype, command,
353 &commandlen ) == ERROR_SUCCESS )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000354 {
355 /* Is there a replace() function anywhere? */
356 command[commandlen]='\0';
357 strcpy( lpResult, command );
358 tok=strstr( lpResult, "%1" );
359 if (tok != NULL)
360 {
361 tok[0]='\0'; /* truncate string at the percent */
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000362 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000363 tok=strstr( command, "%1" );
364 if ((tok!=NULL) && (strlen(tok)>2))
365 {
366 strcat( lpResult, &tok[2] );
367 }
368 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000369 retval=33; /* FIXME see above */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000370 }
371 }
372 else /* Check win.ini */
373 {
374 /* Toss the leading dot */
375 extension++;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000376 if ( GetProfileStringA( "extensions", extension, "", command,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000377 sizeof(command)) > 0)
378 {
379 if (strlen(command)!=0)
380 {
381 strcpy( lpResult, command );
382 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
383 if (tok != NULL)
384 {
385 tok[0]='\0';
386 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
387 tok=strstr( command, "^" ); /* see above */
388 if ((tok != NULL) && (strlen(tok)>5))
389 {
390 strcat( lpResult, &tok[5]);
391 }
392 }
393 retval=33; /* FIXME - see above */
394 }
395 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000396 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000397
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000398 TRACE(shell, "returning %s\n", lpResult);
Alexandre Julliardef702d81996-05-28 18:54:58 +0000399 return retval;
400}
401
402/*************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +0000403 * ShellExecute16 [SHELL.20]
Alexandre Julliardef702d81996-05-28 18:54:58 +0000404 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000405HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
406 LPCSTR lpFile, LPCSTR lpParameters,
407 LPCSTR lpDirectory, INT16 iShowCmd )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000408{ HINSTANCE16 retval=31;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000409 char old_dir[1024];
Alexandre Julliardef702d81996-05-28 18:54:58 +0000410 char cmd[256];
411
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000412 TRACE(shell, "(%04x,'%s','%s','%s','%s',%x)\n",
Alexandre Julliardef702d81996-05-28 18:54:58 +0000413 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
414 lpParameters ? lpParameters : "<null>",
415 lpDirectory ? lpDirectory : "<null>", iShowCmd);
416
417 if (lpFile==NULL) return 0; /* should not happen */
418 if (lpOperation==NULL) /* default is open */
419 lpOperation="open";
420
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000421 if (lpDirectory)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000422 { GetCurrentDirectoryA( sizeof(old_dir), old_dir );
423 SetCurrentDirectoryA( lpDirectory );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000424 }
425
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000426 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000427
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000428 if (retval > 32) /* Found */
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000429 { if (lpParameters)
430 { strcat(cmd," ");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000431 strcat(cmd,lpParameters);
432 }
433
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000434 TRACE(shell,"starting %s\n",cmd);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000435 retval = WinExec( cmd, iShowCmd );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000436 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000437 if (lpDirectory)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000438 SetCurrentDirectoryA( old_dir );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000439 return retval;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000440}
441
Alexandre Julliard21979011997-03-05 08:22:35 +0000442/*************************************************************************
443 * FindExecutable16 (SHELL.21)
444 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000445HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
446 LPSTR lpResult )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000447{ return (HINSTANCE16)FindExecutableA( lpFile, lpDirectory, lpResult );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000448}
449
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000450
451/*************************************************************************
452 * AboutDlgProc16 (SHELL.33)
453 */
Juergen Schmiedba28ba11999-01-23 14:12:48 +0000454BOOL16 WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000455 LPARAM lParam )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000456{ return AboutDlgProc( hWnd, msg, wParam, lParam );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000457}
458
459
460/*************************************************************************
461 * ShellAbout16 (SHELL.22)
462 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000463BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
464 HICON16 hIcon )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000465{ return ShellAboutA( hWnd, szApp, szOtherStuff, hIcon );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000466}
Alexandre Julliard73450d61994-05-18 18:29:32 +0000467
Alexandre Julliard2787be81995-05-22 18:23:01 +0000468/*************************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000469 * SHELL_GetResourceTable
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000470 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000471static DWORD SHELL_GetResourceTable(HFILE hFile,LPBYTE *retptr)
Juergen Schmied72b76d11998-11-15 13:28:00 +0000472{ IMAGE_DOS_HEADER mz_header;
473 char magic[4];
474 int size;
475
476 TRACE(shell,"\n");
477
478 *retptr = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000479 _llseek( hFile, 0, SEEK_SET );
480 if ((_lread(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) || (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
Juergen Schmied72b76d11998-11-15 13:28:00 +0000481 { /* .ICO file ? */
482 if (mz_header.e_cblp == 1)
483 { /* ICONHEADER.idType, must be 1 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000484 *retptr = (LPBYTE)-1;
485 return 1;
Juergen Schmied72b76d11998-11-15 13:28:00 +0000486 }
487 else
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000488 return 0; /* failed */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000489 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000490 _llseek( hFile, mz_header.e_lfanew, SEEK_SET );
Juergen Schmied72b76d11998-11-15 13:28:00 +0000491
Alexandre Julliarda3960291999-02-26 11:11:13 +0000492 if (_lread( hFile, magic, sizeof(magic) ) != sizeof(magic))
Juergen Schmied72b76d11998-11-15 13:28:00 +0000493 return 0;
494
Alexandre Julliarda3960291999-02-26 11:11:13 +0000495 _llseek( hFile, mz_header.e_lfanew, SEEK_SET);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000496
497 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
498 return IMAGE_NT_SIGNATURE;
499
500 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE)
501 { IMAGE_OS2_HEADER ne_header;
502 LPBYTE pTypeInfo = (LPBYTE)-1;
503
Alexandre Julliarda3960291999-02-26 11:11:13 +0000504 if (_lread(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
Juergen Schmied72b76d11998-11-15 13:28:00 +0000505 return 0;
506
507 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE)
508 return 0;
509
510 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
511
512 if( size > sizeof(NE_TYPEINFO) )
513 { pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
514 if( pTypeInfo )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000515 { _llseek(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
516 if( _lread( hFile, (char*)pTypeInfo, size) != size )
Juergen Schmied72b76d11998-11-15 13:28:00 +0000517 { HeapFree( GetProcessHeap(), 0, pTypeInfo);
518 pTypeInfo = NULL;
519 }
520 }
521 }
522 *retptr = pTypeInfo;
523 return IMAGE_OS2_SIGNATURE;
524 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000525 return 0; /* failed */
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000526}
527
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000528/*************************************************************************
529 * SHELL_LoadResource
530 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000531static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
Juergen Schmied72b76d11998-11-15 13:28:00 +0000532{ BYTE* ptr;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000533 HGLOBAL16 handle = DirectResAlloc16( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000534
535 TRACE(shell,"\n");
536
537 if( (ptr = (BYTE*)GlobalLock16( handle )) )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000538 { _llseek( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
539 _lread( hFile, (char*)ptr, pNInfo->length << sizeShift);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000540 return handle;
541 }
542 return 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000543}
544
545/*************************************************************************
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000546 * ICO_LoadIcon
547 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000548static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE hFile, LPicoICONDIRENTRY lpiIDE)
Juergen Schmied72b76d11998-11-15 13:28:00 +0000549{ BYTE* ptr;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000550 HGLOBAL16 handle = DirectResAlloc16( hInst, 0x10, lpiIDE->dwBytesInRes);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000551 TRACE(shell,"\n");
552 if( (ptr = (BYTE*)GlobalLock16( handle )) )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000553 { _llseek( hFile, lpiIDE->dwImageOffset, SEEK_SET);
554 _lread( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000555 return handle;
556 }
557 return 0;
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000558}
559
560/*************************************************************************
561 * ICO_GetIconDirectory
562 *
563 * Read .ico file and build phony ICONDIR struct for GetIconID
564 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000565static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE hFile, LPicoICONDIR* lplpiID )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000566{ WORD id[3]; /* idReserved, idType, idCount */
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000567 LPicoICONDIR lpiID;
568 int i;
569
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000570 TRACE(shell,"\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +0000571 _llseek( hFile, 0, SEEK_SET );
572 if( _lread(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000573
574 /* check .ICO header
575 *
576 * - see http://www.microsoft.com/win32dev/ui/icons.htm
577 */
578
579 if( id[0] || id[1] != 1 || !id[2] ) return 0;
580
581 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
582
Alexandre Julliard889f7421997-04-15 17:19:52 +0000583 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000584
Alexandre Julliarda3960291999-02-26 11:11:13 +0000585 if( _lread(hFile,(char*)lpiID->idEntries,i) == i )
586 { HGLOBAL16 handle = DirectResAlloc16( hInst, 0x10,
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000587 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000588 if( handle )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000589 { CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000590 lpID->idReserved = lpiID->idReserved = id[0];
591 lpID->idType = lpiID->idType = id[1];
592 lpID->idCount = lpiID->idCount = id[2];
593 for( i=0; i < lpiID->idCount; i++ )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000594 { memcpy((void*)(lpID->idEntries + i),
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000595 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
596 lpID->idEntries[i].icon.wResId = i;
597 }
598 *lplpiID = lpiID;
599 return handle;
600 }
601 }
602 /* fail */
603
Alexandre Julliard889f7421997-04-15 17:19:52 +0000604 HeapFree( GetProcessHeap(), 0, lpiID);
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000605 return 0;
606}
607
608/*************************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000609 * InternalExtractIcon [SHELL.39]
610 *
611 * This abortion is called directly by Progman
612 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000613HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
Juergen Schmied72b76d11998-11-15 13:28:00 +0000614 LPCSTR lpszExeFileName, UINT16 nIconIndex, WORD n )
615{ HGLOBAL16 hRet = 0;
616 HGLOBAL16* RetPtr = NULL;
617 LPBYTE pData;
618 OFSTRUCT ofs;
619 DWORD sig;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000620 HFILE hFile = OpenFile( lpszExeFileName, &ofs, OF_READ );
Juergen Schmied72b76d11998-11-15 13:28:00 +0000621 UINT16 iconDirCount = 0,iconCount = 0;
622 LPBYTE peimage;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000623 HANDLE fmapping;
Juergen Schmied72b76d11998-11-15 13:28:00 +0000624
625 TRACE(shell,"(%04x,file %s,start %d,extract %d\n",
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000626 hInstance, lpszExeFileName, nIconIndex, n);
627
Alexandre Julliarda3960291999-02-26 11:11:13 +0000628 if( hFile == HFILE_ERROR || !n )
Juergen Schmied72b76d11998-11-15 13:28:00 +0000629 return 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000630
Juergen Schmied72b76d11998-11-15 13:28:00 +0000631 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
632 RetPtr = (HICON16*)GlobalLock16(hRet);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000633
Juergen Schmied72b76d11998-11-15 13:28:00 +0000634 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000635
Juergen Schmied72b76d11998-11-15 13:28:00 +0000636 sig = SHELL_GetResourceTable(hFile,&pData);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000637
Juergen Schmied72b76d11998-11-15 13:28:00 +0000638 if( sig==IMAGE_OS2_SIGNATURE || sig==1 ) /* .ICO file */
639 { HICON16 hIcon = 0;
640 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
641 NE_NAMEINFO* pIconStorage = NULL;
642 NE_NAMEINFO* pIconDir = NULL;
643 LPicoICONDIR lpiID = NULL;
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000644
Juergen Schmied72b76d11998-11-15 13:28:00 +0000645 if( pData == (BYTE*)-1 )
646 { hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID); /* check for .ICO file */
647 if( hIcon )
648 { iconDirCount = 1; iconCount = lpiID->idCount;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000649 }
Juergen Schmied72b76d11998-11-15 13:28:00 +0000650 }
651 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
652 { if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON ) /* find icon directory and icon repository */
653 { iconDirCount = pTInfo->count;
654 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
655 TRACE(shell,"\tfound directory - %i icon families\n", iconDirCount);
656 }
657 if( pTInfo->type_id == NE_RSCTYPE_ICON )
658 { iconCount = pTInfo->count;
659 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
660 TRACE(shell,"\ttotal icons - %i\n", iconCount);
661 }
662 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
663 }
664
665 /* load resources and create icons */
666
667 if( (pIconStorage && pIconDir) || lpiID )
668 { if( nIconIndex == (UINT16)-1 )
669 { RetPtr[0] = iconDirCount;
670 }
671 else if( nIconIndex < iconDirCount )
672 { UINT16 i, icon;
673 if( n > iconDirCount - nIconIndex )
674 n = iconDirCount - nIconIndex;
675
676 for( i = nIconIndex; i < nIconIndex + n; i++ )
677 { /* .ICO files have only one icon directory */
678
679 if( lpiID == NULL )
680 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i, *(WORD*)pData );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000681 RetPtr[i-nIconIndex] = GetIconID16( hIcon, 3 );
Juergen Schmied72b76d11998-11-15 13:28:00 +0000682 GlobalFree16(hIcon);
683 }
684
685 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
686 { hIcon = 0;
687 if( lpiID )
688 { hIcon = ICO_LoadIcon( hInstance, hFile, lpiID->idEntries + RetPtr[icon-nIconIndex]);
689 }
690 else
691 { for( i = 0; i < iconCount; i++ )
692 { if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
693 { hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,*(WORD*)pData );
694 }
695 }
696 }
697 if( hIcon )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000698 { RetPtr[icon-nIconIndex] = LoadIconHandler16( hIcon, TRUE );
699 FarSetOwner16( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
Juergen Schmied72b76d11998-11-15 13:28:00 +0000700 }
701 else
702 { RetPtr[icon-nIconIndex] = 0;
703 }
704 }
705 }
706 }
707 if( lpiID )
708 HeapFree( GetProcessHeap(), 0, lpiID);
709 else
710 HeapFree( GetProcessHeap(), 0, pData);
711 }
712
713 if( sig == IMAGE_NT_SIGNATURE)
714 { LPBYTE idata,igdata;
715 PIMAGE_DOS_HEADER dheader;
716 PIMAGE_NT_HEADERS pe_header;
717 PIMAGE_SECTION_HEADER pe_sections;
718 PIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
719 PIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
720 int i,j;
721 PIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
722 CURSORICONDIR **cids;
723
Alexandre Julliarda3960291999-02-26 11:11:13 +0000724 fmapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000725 if (fmapping == 0)
726 { /* FIXME, INVALID_HANDLE_VALUE? */
727 WARN(shell,"failed to create filemap.\n");
728 hRet = 0;
729 goto end_2; /* failure */
730 }
731 peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
732 if (!peimage)
733 { WARN(shell,"failed to mmap filemap.\n");
734 hRet = 0;
735 goto end_2; /* failure */
736 }
737 dheader = (PIMAGE_DOS_HEADER)peimage;
738
739 /* it is a pe header, SHELL_GetResourceTable checked that */
740 pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
741
742 /* probably makes problems with short PE headers... but I haven't seen
743 * one yet...
744 */
745 pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
746 rootresdir = NULL;
747
748 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++)
749 { if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
750 continue;
751 /* FIXME: doesn't work when the resources are not in a seperate section */
752 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)
753 { rootresdir = (PIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
754 break;
755 }
756 }
757
758 if (!rootresdir)
759 { WARN(shell,"haven't found section for resource directory.\n");
760 goto end_4; /* failure */
761 }
762
Alexandre Julliarda3960291999-02-26 11:11:13 +0000763 icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICONW, (DWORD)rootresdir,FALSE);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000764
765 if (!icongroupresdir)
766 { WARN(shell,"No Icongroupresourcedirectory!\n");
767 goto end_4; /* failure */
768 }
769
770 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
771
772 if( nIconIndex == (UINT16)-1 )
773 { RetPtr[0] = iconDirCount;
774 goto end_3; /* success */
775 }
776
777 if (nIconIndex >= iconDirCount)
778 { WARN(shell,"nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
779 GlobalFree16(hRet);
780 goto end_4; /* failure */
781 }
782
783 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
784
785 /* caller just wanted the number of entries */
786 xresent = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
787
788 /* assure we don't get too much ... */
789 if( n > iconDirCount - nIconIndex )
790 { n = iconDirCount - nIconIndex;
791 }
792
793 /* starting from specified index ... */
794 xresent = xresent+nIconIndex;
795
796 for (i=0;i<n;i++,xresent++)
797 { CURSORICONDIR *cid;
798 PIMAGE_RESOURCE_DIRECTORY resdir;
799
800 /* go down this resource entry, name */
801 resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
802
803 /* default language (0) */
804 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
805 igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir;
806
807 /* lookup address in mapped image for virtual address */
808 igdata = NULL;
809
810 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
811 { if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
812 continue;
813 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000814 continue;
Juergen Schmied72b76d11998-11-15 13:28:00 +0000815 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
816 }
817
818 if (!igdata)
819 { WARN(shell,"no matching real address for icongroup!\n");
820 goto end_4; /* failure */
821 }
822 /* found */
823 cid = (CURSORICONDIR*)igdata;
824 cids[i] = cid;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000825 RetPtr[i] = LookupIconIdFromDirectoryEx(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000826 }
827
Alexandre Julliarda3960291999-02-26 11:11:13 +0000828 iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,(DWORD)rootresdir,FALSE);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000829
830 if (!iconresdir)
831 { WARN(shell,"No Iconresourcedirectory!\n");
832 goto end_4; /* failure */
833 }
834
835 for (i=0;i<n;i++)
836 { PIMAGE_RESOURCE_DIRECTORY xresdir;
837 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],(DWORD)rootresdir,FALSE);
838 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
839 idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir;
840 idata = NULL;
841
842 /* map virtual to address in image */
843 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
844 { if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
845 continue;
846 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
847 continue;
848 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
849 }
850 if (!idata)
851 { WARN(shell,"no matching real address found for icondata!\n");
852 RetPtr[i]=0;
853 continue;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000854 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000855 RetPtr[i] = CreateIconFromResourceEx(idata,idataent->Size,TRUE,0x00030000,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000856 }
857 goto end_3; /* sucess */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000858 }
Juergen Schmied72b76d11998-11-15 13:28:00 +0000859 goto end_1; /* return array with icon handles */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000860
Juergen Schmied72b76d11998-11-15 13:28:00 +0000861/* cleaning up (try & catch would be nicer) */
862end_4: hRet = 0; /* failure */
863end_3: UnmapViewOfFile(peimage); /* success */
864end_2: CloseHandle(fmapping);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000865end_1: _lclose( hFile);
Juergen Schmied72b76d11998-11-15 13:28:00 +0000866 return hRet;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000867}
868
869/*************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +0000870 * ExtractIcon16 (SHELL.34)
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000871 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000872HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
Alexandre Julliarde658d821997-11-30 17:45:40 +0000873 UINT16 nIconIndex )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000874{ TRACE(shell,"\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +0000875 return ExtractIconA( hInstance, lpszExeFileName, nIconIndex );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000876}
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000877
Marcus Meissner628e3e01999-01-23 11:56:39 +0000878/*************************************************************************
879 * ExtractIconEx16 (SHELL.40)
880 */
881HICON16 WINAPI ExtractIconEx16(
882 LPCSTR lpszFile, INT16 nIconIndex, HICON16 *phiconLarge,
883 HICON16 *phiconSmall, UINT16 nIcons
884) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000885 HICON *ilarge,*ismall;
Marcus Meissner628e3e01999-01-23 11:56:39 +0000886 UINT16 ret;
887 int i;
Alexandre Julliard21979011997-03-05 08:22:35 +0000888
Marcus Meissner628e3e01999-01-23 11:56:39 +0000889 if (phiconLarge)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000890 ilarge = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON));
Marcus Meissner628e3e01999-01-23 11:56:39 +0000891 else
892 ilarge = NULL;
893 if (phiconSmall)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000894 ismall = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON));
Marcus Meissner628e3e01999-01-23 11:56:39 +0000895 else
896 ismall = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000897 ret = ExtractIconExA(lpszFile,nIconIndex,ilarge,ismall,nIcons);
Marcus Meissner628e3e01999-01-23 11:56:39 +0000898 if (ilarge) {
899 for (i=0;i<nIcons;i++)
900 phiconLarge[i]=ilarge[i];
901 HeapFree(GetProcessHeap(),0,ilarge);
902 }
903 if (ismall) {
904 for (i=0;i<nIcons;i++)
905 phiconSmall[i]=ismall[i];
906 HeapFree(GetProcessHeap(),0,ismall);
907 }
908 return ret;
909}
Alexandre Julliard21979011997-03-05 08:22:35 +0000910
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000911/*************************************************************************
912 * ExtractAssociatedIcon [SHELL.36]
Alexandre Julliard8b915631996-06-16 16:16:05 +0000913 *
914 * Return icon for given file (either from file itself or from associated
915 * executable) and patch parameters if needed.
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000916 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000917HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)
Juergen Schmied72b76d11998-11-15 13:28:00 +0000918{ TRACE(shell,"\n");
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000919 return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
920}
921
Juergen Schmied72b76d11998-11-15 13:28:00 +0000922HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst, LPSTR lpIconPath, LPWORD lpiIcon)
923{ HICON16 hIcon;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000924
Juergen Schmied72b76d11998-11-15 13:28:00 +0000925 TRACE(shell,"\n");
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000926
Juergen Schmied72b76d11998-11-15 13:28:00 +0000927 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000928
Juergen Schmied72b76d11998-11-15 13:28:00 +0000929 if( hIcon < 2 )
930 { if( hIcon == 1 ) /* no icons found in given file */
931 { char tempPath[0x80];
Alexandre Julliard21979011997-03-05 08:22:35 +0000932 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
Alexandre Julliard8b915631996-06-16 16:16:05 +0000933
934 if( uRet > 32 && tempPath[0] )
Juergen Schmied72b76d11998-11-15 13:28:00 +0000935 { strcpy(lpIconPath,tempPath);
936 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
937 if( hIcon > 2 )
938 return hIcon;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000939 }
Alexandre Julliard8b915631996-06-16 16:16:05 +0000940 else hIcon = 0;
Juergen Schmied72b76d11998-11-15 13:28:00 +0000941 }
Alexandre Julliard8b915631996-06-16 16:16:05 +0000942
Juergen Schmied72b76d11998-11-15 13:28:00 +0000943 if( hIcon == 1 )
Alexandre Julliarde658d821997-11-30 17:45:40 +0000944 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
Juergen Schmied72b76d11998-11-15 13:28:00 +0000945 else
Alexandre Julliarde658d821997-11-30 17:45:40 +0000946 *lpiIcon = 6; /* generic icon - found nothing */
947
Juergen Schmied72b76d11998-11-15 13:28:00 +0000948 GetModuleFileName16(hInst, lpIconPath, 0x80);
949 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE16(*lpiIcon));
950 }
951 return hIcon;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000952}
953
954/*************************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000955 * FindEnvironmentString [SHELL.38]
956 *
957 * Returns a pointer into the DOS environment... Ugh.
Alexandre Julliard2787be81995-05-22 18:23:01 +0000958 */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000959LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000960{ UINT16 l;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000961
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000962 TRACE(shell,"\n");
963
964 l = strlen(entry);
965 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000966 { if( lstrncmpiA(lpEnv, entry, l) )
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000967 continue;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000968 if( !*(lpEnv+l) )
969 return (lpEnv + l); /* empty entry */
970 else if ( *(lpEnv+l)== '=' )
971 return (lpEnv + l + 1);
972 }
973 return NULL;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000974}
975
Alexandre Julliarda3960291999-02-26 11:11:13 +0000976SEGPTR WINAPI FindEnvironmentString16(LPSTR str)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000977{ SEGPTR spEnv;
978 LPSTR lpEnv,lpString;
979 TRACE(shell,"\n");
980
Alexandre Julliarda3960291999-02-26 11:11:13 +0000981 spEnv = GetDOSEnvironment16();
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000982
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000983 lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
984 lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000985
Alexandre Julliarde658d821997-11-30 17:45:40 +0000986 if( lpString ) /* offset should be small enough */
987 return spEnv + (lpString - lpEnv);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000988 return (SEGPTR)NULL;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000989}
990
991/*************************************************************************
992 * DoEnvironmentSubst [SHELL.37]
993 *
994 * Replace %KEYWORD% in the str with the value of variable KEYWORD
995 * from "DOS" environment.
996 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000997DWORD WINAPI DoEnvironmentSubst16(LPSTR str,WORD length)
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000998{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000999 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment16());
Alexandre Julliard889f7421997-04-15 17:19:52 +00001000 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001001 LPSTR lpstr = str;
1002 LPSTR lpbstr = lpBuffer;
1003
Alexandre Julliarda3960291999-02-26 11:11:13 +00001004 CharToOemA(str,str);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001005
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001006 TRACE(shell,"accept %s\n", str);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001007
1008 while( *lpstr && lpbstr - lpBuffer < length )
1009 {
1010 LPSTR lpend = lpstr;
1011
1012 if( *lpstr == '%' )
1013 {
1014 do { lpend++; } while( *lpend && *lpend != '%' );
1015 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
1016 {
1017 LPSTR lpKey;
1018 *lpend = '\0';
1019 lpKey = SHELL_FindString(lpEnv, lpstr+1);
1020 if( lpKey ) /* found key value */
1021 {
1022 int l = strlen(lpKey);
1023
1024 if( l > length - (lpbstr - lpBuffer) - 1 )
1025 {
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001026 WARN(shell,"-- Env subst aborted - string too short\n");
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001027 *lpend = '%';
1028 break;
1029 }
1030 strcpy(lpbstr, lpKey);
1031 lpbstr += l;
1032 }
1033 else break;
1034 *lpend = '%';
1035 lpstr = lpend + 1;
1036 }
1037 else break; /* back off and whine */
1038
1039 continue;
1040 }
1041
1042 *lpbstr++ = *lpstr++;
1043 }
1044
1045 *lpbstr = '\0';
1046 if( lpstr - str == strlen(str) )
1047 {
1048 strncpy(str, lpBuffer, length);
1049 length = 1;
1050 }
1051 else
1052 length = 0;
1053
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001054 TRACE(shell,"-- return %s\n", str);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001055
Alexandre Julliarda3960291999-02-26 11:11:13 +00001056 OemToCharA(str,str);
Alexandre Julliard889f7421997-04-15 17:19:52 +00001057 HeapFree( GetProcessHeap(), 0, lpBuffer);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001058
1059 /* Return str length in the LOWORD
1060 * and 1 in HIWORD if subst was successful.
1061 */
1062 return (DWORD)MAKELONG(strlen(str), length);
Alexandre Julliardd18872d1994-05-11 12:18:19 +00001063}
1064
1065/*************************************************************************
Alexandre Julliard889f7421997-04-15 17:19:52 +00001066 * ShellHookProc [SHELL.103]
1067 * System-wide WH_SHELL hook.
Alexandre Julliard58199531994-04-21 01:20:00 +00001068 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001069LRESULT WINAPI ShellHookProc16(INT16 code, WPARAM16 wParam, LPARAM lParam)
Alexandre Julliard58199531994-04-21 01:20:00 +00001070{
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001071 TRACE(shell,"%i, %04x, %08x\n", code, wParam,
Alexandre Julliard889f7421997-04-15 17:19:52 +00001072 (unsigned)lParam );
1073 if( SHELL_hHook && SHELL_hWnd )
1074 {
1075 UINT16 uMsg = 0;
1076 switch( code )
1077 {
1078 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
1079 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
1080 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
1081 }
1082 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
1083 }
1084 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
Alexandre Julliard58199531994-04-21 01:20:00 +00001085}
1086
1087/*************************************************************************
Alexandre Julliard889f7421997-04-15 17:19:52 +00001088 * RegisterShellHook [SHELL.102]
Alexandre Julliard58199531994-04-21 01:20:00 +00001089 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001090BOOL WINAPI RegisterShellHook16(HWND16 hWnd, UINT16 uAction)
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001091{ TRACE(shell,"%04x [%u]\n", hWnd, uAction );
Alexandre Julliard889f7421997-04-15 17:19:52 +00001092
1093 switch( uAction )
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001094 { case 2: /* register hWnd as a shell window */
Alexandre Julliard889f7421997-04-15 17:19:52 +00001095 if( !SHELL_hHook )
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001096 { HMODULE16 hShell = GetModuleHandle16( "SHELL" );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001097 SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc16, hShell, 0 );
Alexandre Julliard889f7421997-04-15 17:19:52 +00001098 if( SHELL_hHook )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001099 { uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated );
1100 uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed );
1101 uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate );
Alexandre Julliard889f7421997-04-15 17:19:52 +00001102 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001103 else
1104 WARN(shell,"-- unable to install ShellHookProc()!\n");
Alexandre Julliard889f7421997-04-15 17:19:52 +00001105 }
1106
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001107 if( SHELL_hHook )
1108 return ((SHELL_hWnd = hWnd) != 0);
Alexandre Julliard889f7421997-04-15 17:19:52 +00001109 break;
1110
1111 default:
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001112 WARN(shell, "-- unknown code %i\n", uAction );
Alexandre Julliard889f7421997-04-15 17:19:52 +00001113 /* just in case */
Alexandre Julliard889f7421997-04-15 17:19:52 +00001114 SHELL_hWnd = 0;
1115 }
1116 return FALSE;
Alexandre Julliard58199531994-04-21 01:20:00 +00001117}