source: trunk/src/shell32/shell.cpp@ 1330

Last change on this file since 1330 was 1215, checked in by sandervl, 26 years ago

Added $Id$

File size: 14.6 KB
Line 
1/* $Id: shell.cpp,v 1.2 1999-10-09 11:17:01 sandervl Exp $ */
2/*
3 * Shell Library Functions
4 *
5 * 1998 Marcus Meissner
6 */
7#include <assert.h>
8#include <stdlib.h>
9#include <string.h>
10//#include <unistd.h>
11#include <ctype.h>
12
13#include <odin.h>
14
15#define ICOM_CINTERFACE 1
16#define CINTERFACE 1
17
18#include <winbase.h>
19#include <winuser.h>
20//#include "wine/shell16.h"
21#include "winerror.h"
22//#include "file.h"
23#include "heap.h"
24#include "ldt.h"
25#include "module.h"
26#include "neexe.h"
27#include "dlgs.h"
28#include "cursoricon.h"
29#include "shellapi.h"
30#include "shlobj.h"
31#include "debugtools.h"
32#include "winreg.h"
33//#include "syslevel.h"
34#include "imagelist.h"
35#include "shell32_main.h"
36
37#include <heapstring.h>
38#include <misc.h>
39
40DECLARE_DEBUG_CHANNEL(exec)
41DECLARE_DEBUG_CHANNEL(shell)
42
43/* .ICO file ICONDIR definitions */
44
45#include "pshpack1.h"
46
47typedef struct
48{
49 BYTE bWidth; /* Width, in pixels, of the image */
50 BYTE bHeight; /* Height, in pixels, of the image */
51 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
52 BYTE bReserved; /* Reserved ( must be 0) */
53 WORD wPlanes; /* Color Planes */
54 WORD wBitCount; /* Bits per pixel */
55 DWORD dwBytesInRes; /* How many bytes in this resource? */
56 DWORD dwImageOffset; /* Where in the file is this image? */
57} icoICONDIRENTRY, *LPicoICONDIRENTRY;
58
59typedef struct
60{
61 WORD idReserved; /* Reserved (must be 0) */
62 WORD idType; /* Resource Type (1 for icons) */
63 WORD idCount; /* How many images? */
64 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
65} icoICONDIR, *LPicoICONDIR;
66
67#include "poppack.h"
68
69static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
70static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
71static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
72
73static HWND16 SHELL_hWnd = 0;
74static HHOOK SHELL_hHook = 0;
75static UINT16 uMsgWndCreated = 0;
76static UINT16 uMsgWndDestroyed = 0;
77static UINT16 uMsgShellActivate = 0;
78HINSTANCE16 SHELL_hInstance = 0;
79HINSTANCE SHELL_hInstance32;
80static int SHELL_Attach = 0;
81
82
83/*************************************************************************
84 * DragAcceptFiles32 [SHELL32.54]
85 */
86void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
87{
88 LONG exstyle;
89
90
91 if( !IsWindow(hWnd) )
92 return;
93 exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
94 if (b)exstyle |= WS_EX_ACCEPTFILES;
95 else exstyle &= ~WS_EX_ACCEPTFILES;
96 SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
97}
98
99/*************************************************************************
100 * SHELL_DragQueryFile [internal]
101 *
102 */
103static UINT SHELL_DragQueryFile(LPSTR lpDrop, LPWSTR lpwDrop, UINT lFile,
104 LPSTR lpszFile, LPWSTR lpszwFile, UINT lLength)
105{
106 UINT i;
107
108 i = 0;
109 if (lpDrop) {
110 while (i++ < lFile) {
111 while (*lpDrop++); /* skip filename */
112 if (!*lpDrop)
113 return (lFile == 0xFFFFFFFF) ? i : 0;
114 }
115 }
116 if (lpwDrop) {
117 while (i++ < lFile) {
118 while (*lpwDrop++); /* skip filename */
119 if (!*lpwDrop)
120 return (lFile == 0xFFFFFFFF) ? i : 0;
121 }
122 }
123
124 if (lpDrop) i = lstrlenA(lpDrop);
125 if (lpwDrop) i = lstrlenW(lpwDrop);
126 i++;
127 if (!lpszFile && !lpszwFile) {
128 return i; /* needed buffer size */
129 }
130 i = (lLength > i) ? i : lLength;
131 if (lpszFile) {
132 if (lpDrop) lstrcpynA (lpszFile, lpDrop, i);
133 else lstrcpynWtoA(lpszFile, lpwDrop, i);
134 } else {
135 if (lpDrop) lstrcpynAtoW(lpszwFile, lpDrop, i);
136 else lstrcpynW (lpszwFile, lpwDrop, i);
137 }
138 return i;
139}
140
141/*************************************************************************
142 * DragQueryFile32A [SHELL32.81] [shell32.82]
143 */
144UINT WINAPI DragQueryFileA(HDROP hDrop, UINT lFile, LPSTR lpszFile,
145 UINT lLength)
146{ /* hDrop is a global memory block allocated with GMEM_SHARE
147 * with DROPFILESTRUCT as a header and filenames following
148 * it, zero length filename is in the end */
149
150 LPDROPFILESTRUCT lpDropFileStruct;
151 LPSTR lpCurrent;
152 UINT i;
153
154 TRACE_(shell)("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
155
156 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
157 if(!lpDropFileStruct)
158 return 0;
159
160 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->lSize;
161 i = SHELL_DragQueryFile(lpCurrent, NULL, lFile, lpszFile, NULL, lLength);
162 GlobalUnlock(hDrop);
163 return i;
164}
165
166/*************************************************************************
167 * DragQueryFile32W [shell32.133]
168 */
169UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile,
170 UINT lLength)
171{
172 LPDROPFILESTRUCT lpDropFileStruct;
173 LPWSTR lpwCurrent;
174 UINT i;
175
176 TRACE_(shell)("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
177
178 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
179 if(!lpDropFileStruct)
180 return 0;
181
182 lpwCurrent = (LPWSTR) lpDropFileStruct + lpDropFileStruct->lSize;
183 i = SHELL_DragQueryFile(NULL, lpwCurrent, lFile, NULL, lpszwFile,lLength);
184 GlobalUnlock(hDrop);
185 return i;
186}
187
188
189/*****************************************************************************
190 * Name : UINT DragQueryFileAorW
191 * Purpose :
192 * Parameters: HDROP hDrop - drop structure handle
193 * UINT iFile - index of file to query
194 * LPTSTR lpszFile - target buffer
195 * UINT cch - target buffer size
196 * Variables :
197 * Result :
198 * Remark :
199 * Status : UNTESTED STUB
200 *
201 * Author : Patrick Haller [Tue, 1999/06/09 20:00]
202 *****************************************************************************/
203
204UINT WIN32API DragQueryFileAorW(HDROP hDrop,
205 UINT iFile,
206 LPTSTR lpszFile,
207 UINT cch)
208{
209 dprintf(("SHELL32: DragQueryFileAorW(%08xh,%08xh,%s,%08xh).\n",
210 hDrop,
211 iFile,
212 lpszFile,
213 cch));
214
215 // @@@PH maybe they want automatic determination here
216 if (VERSION_OsIsUnicode())
217 return DragQueryFileW(hDrop, iFile, (LPWSTR)lpszFile, cch);
218 else
219 return DragQueryFileA(hDrop, iFile, lpszFile, cch);
220}
221
222
223/*************************************************************************
224 * DragFinish32 [SHELL32.80]
225 */
226void WINAPI DragFinish(HDROP h)
227{ TRACE_(shell)("\n");
228 GlobalFree((HGLOBAL)h);
229}
230
231
232/*************************************************************************
233 * DragQueryPoint32 [SHELL32.135]
234 */
235BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
236{
237 LPDROPFILESTRUCT lpDropFileStruct;
238 BOOL bRet;
239 TRACE_(shell)("\n");
240 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
241
242 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT));
243 bRet = lpDropFileStruct->fInNonClientArea;
244
245 GlobalUnlock(hDrop);
246 return bRet;
247}
248
249/*************************************************************************
250 * SHELL_FindExecutable [Internal]
251 *
252 * Utility for code sharing between FindExecutable and ShellExecute
253 */
254HINSTANCE SHELL_FindExecutable( LPCSTR lpFile,
255 LPCSTR lpOperation,
256 LPSTR lpResult)
257{ char *extension = NULL; /* pointer to file extension */
258 char tmpext[5]; /* local copy to mung as we please */
259 char filetype[256]; /* registry name for this filetype */
260 LONG filetypelen=256; /* length of above */
261 char command[256]; /* command from registry */
262 LONG commandlen=256; /* This is the most DOS can handle :) */
263 char buffer[256]; /* Used to GetProfileString */
264 HINSTANCE retval=31; /* default - 'No association was found' */
265 char *tok; /* token pointer */
266 int i; /* random counter */
267 char xlpFile[256]; /* result of SearchPath */
268
269 TRACE_(shell)("%s\n", (lpFile != NULL?lpFile:"-") );
270
271 lpResult[0]='\0'; /* Start off with an empty return string */
272
273 /* trap NULL parameters on entry */
274 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
275 { WARN_(exec)("(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n",
276 lpFile, lpOperation, lpResult);
277 return 2; /* File not found. Close enough, I guess. */
278 }
279
280 if (SearchPathA( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
281 { TRACE_(shell)("SearchPath32A returned non-zero\n");
282 lpFile = xlpFile;
283 }
284
285 /* First thing we need is the file's extension */
286 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
287 /* File->Run in progman uses */
288 /* .\FILE.EXE :( */
289 TRACE_(shell)("xlpFile=%s,extension=%s\n", xlpFile, extension);
290
291 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
292 { WARN_(shell)("Returning 31 - No association\n");
293 return 31; /* no association */
294 }
295
296 /* Make local copy & lowercase it for reg & 'programs=' lookup */
297 lstrcpynA( tmpext, extension, 5 );
298 CharLowerA( tmpext );
299 TRACE_(shell)("%s file\n", tmpext);
300
301 /* Three places to check: */
302 /* 1. win.ini, [windows], programs (NB no leading '.') */
303 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
304 /* 3. win.ini, [extensions], extension (NB no leading '.' */
305 /* All I know of the order is that registry is checked before */
306 /* extensions; however, it'd make sense to check the programs */
307 /* section first, so that's what happens here. */
308
309 /* See if it's a program - if GetProfileString fails, we skip this
310 * section. Actually, if GetProfileString fails, we've probably
311 * got a lot more to worry about than running a program... */
312 if ( GetProfileStringA("windows", "programs", "exe pif bat com",
313 buffer, sizeof(buffer)) > 0 )
314 { for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
315
316 tok = strtok(buffer, " \t"); /* ? */
317 while( tok!= NULL)
318 {
319 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
320 {
321 strcpy(lpResult, xlpFile);
322 /* Need to perhaps check that the file has a path
323 * attached */
324 TRACE_(shell)("found %s\n", lpResult);
325 return 33;
326
327 /* Greater than 32 to indicate success FIXME According to the
328 * docs, I should be returning a handle for the
329 * executable. Does this mean I'm supposed to open the
330 * executable file or something? More RTFM, I guess... */
331 }
332 tok=strtok(NULL, " \t");
333 }
334 }
335
336 /* Check registry */
337 if (RegQueryValueA( HKEY_CLASSES_ROOT, tmpext, filetype,
338 &filetypelen ) == ERROR_SUCCESS )
339 {
340 filetype[filetypelen]='\0';
341 TRACE_(shell)("File type: %s\n", filetype);
342
343 /* Looking for ...buffer\shell\lpOperation\command */
344 strcat( filetype, "\\shell\\" );
345 strcat( filetype, lpOperation );
346 strcat( filetype, "\\command" );
347
348 if (RegQueryValueA( HKEY_CLASSES_ROOT, filetype, command,
349 &commandlen ) == ERROR_SUCCESS )
350 {
351 /* Is there a replace() function anywhere? */
352 command[commandlen]='\0';
353 strcpy( lpResult, command );
354 tok=strstr( lpResult, "%1" );
355 if (tok != NULL)
356 {
357 tok[0]='\0'; /* truncate string at the percent */
358 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
359 tok=strstr( command, "%1" );
360 if ((tok!=NULL) && (strlen(tok)>2))
361 {
362 strcat( lpResult, &tok[2] );
363 }
364 }
365 retval=33; /* FIXME see above */
366 }
367 }
368 else /* Check win.ini */
369 {
370 /* Toss the leading dot */
371 extension++;
372 if ( GetProfileStringA( "extensions", extension, "", command,
373 sizeof(command)) > 0)
374 {
375 if (strlen(command)!=0)
376 {
377 strcpy( lpResult, command );
378 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
379 if (tok != NULL)
380 {
381 tok[0]='\0';
382 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
383 tok=strstr( command, "^" ); /* see above */
384 if ((tok != NULL) && (strlen(tok)>5))
385 {
386 strcat( lpResult, &tok[5]);
387 }
388 }
389 retval=33; /* FIXME - see above */
390 }
391 }
392 }
393
394 TRACE_(shell)("returning %s\n", lpResult);
395 return retval;
396}
397
398
399/*************************************************************************
400 * SHELL_GetResourceTable
401 */
402static DWORD SHELL_GetResourceTable(HFILE hFile,LPBYTE *retptr)
403{ IMAGE_DOS_HEADER mz_header;
404 char magic[4];
405 int size;
406
407 TRACE_(shell)("\n");
408
409 *retptr = NULL;
410 _llseek( hFile, 0, SEEK_SET );
411 if ((_lread(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) || (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
412 { /* .ICO file ? */
413 if (mz_header.e_cblp == 1)
414 { /* ICONHEADER.idType, must be 1 */
415 *retptr = (LPBYTE)-1;
416 return 1;
417 }
418 else
419 return 0; /* failed */
420 }
421 _llseek( hFile, mz_header.e_lfanew, SEEK_SET );
422
423 if (_lread( hFile, magic, sizeof(magic) ) != sizeof(magic))
424 return 0;
425
426 _llseek( hFile, mz_header.e_lfanew, SEEK_SET);
427
428 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
429 return IMAGE_NT_SIGNATURE;
430
431 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE)
432 { IMAGE_OS2_HEADER ne_header;
433 LPBYTE pTypeInfo = (LPBYTE)-1;
434
435 if (_lread(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
436 return 0;
437
438 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE)
439 return 0;
440
441 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
442
443//@@@PH no NE support
444#if 0
445 if( size > sizeof(NE_TYPEINFO) )
446 { pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
447 if( pTypeInfo )
448 { _llseek(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
449 if( _lread( hFile, (char*)pTypeInfo, size) != size )
450 { HeapFree( GetProcessHeap(), 0, pTypeInfo);
451 pTypeInfo = NULL;
452 }
453 }
454 }
455#endif
456
457 *retptr = pTypeInfo;
458 return IMAGE_OS2_SIGNATURE;
459 }
460 return 0; /* failed */
461}
462
463
464/*************************************************************************
465 * ExtractAssociatedIcon [SHELL.36]
466 *
467 * Return icon for given file (either from file itself or from associated
468 * executable) and patch parameters if needed.
469 */
470HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)
471{ TRACE_(shell)("\n");
472 HICON hIcon;
473
474 hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon);
475
476 if( hIcon < 2 )
477 { if( hIcon == 1 ) /* no icons found in given file */
478 { char tempPath[0x104];
479 UINT16 uRet = FindExecutableA(lpIconPath,NULL,tempPath);
480
481 if( uRet > 32 && tempPath[0] )
482 { strcpy(lpIconPath,tempPath);
483 hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon);
484 if( hIcon > 2 )
485 return hIcon;
486 }
487 else hIcon = 0;
488 }
489
490 if( hIcon == 1 )
491 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
492 else
493 *lpiIcon = 6; /* generic icon - found nothing */
494
495 GetModuleFileNameA(hInst, lpIconPath, 0x80);
496 hIcon = LoadIconA( hInst, (LPCSTR)*lpiIcon);
497 }
498 return hIcon;
499}
Note: See TracBrowser for help on using the repository browser.