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

Last change on this file since 2013 was 1353, checked in by phaller, 26 years ago

Fix: debug info

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