source: trunk/src/shell32/shell32_odin.cpp@ 8614

Last change on this file since 8614 was 8614, checked in by sandervl, 23 years ago

compile fixes

File size: 40.0 KB
Line 
1/* $Id: shell32_odin.cpp,v 1.5 2002-06-09 12:41:22 sandervl 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 basics
10 *
11 * 1998 Marcus Meissner
12 * 1998 Juergen Schmied (jsch) * <juergen.schmied@metronet.de>
13 *
14 */
15
16/*****************************************************************************
17 * Includes *
18 *****************************************************************************/
19
20#include <odin.h>
21#include <odinwrap.h>
22#include <os2sel.h>
23
24#include <stdlib.h>
25#include <string.h>
26
27#define ICOM_CINTERFACE 1
28#define CINTERFACE 1
29
30#include "winerror.h"
31#include "heap.h"
32#include "resource.h"
33#include "dlgs.h"
34#include "sysmetrics.h"
35#include "debugtools.h"
36#include "winreg.h"
37#include "authors.h"
38#include "winversion.h"
39
40#include "shellapi.h"
41#include "pidl.h"
42
43#include "shlobj.h"
44#include "shell32_main.h"
45#include "shlguid.h"
46#include "undocshell.h"
47#include "shpolicy.h"
48#include "shlwapi.h"
49
50#include <heapstring.h>
51#include <misc.h>
52#include <peexe.h>
53#include <neexe.h>
54#include <cursoricon.h>
55#include <ctype.h>
56#include <module.h>
57
58#include "os2_integration.h"
59
60
61/*****************************************************************************
62 * Local Variables *
63 *****************************************************************************/
64
65ODINDEBUGCHANNEL(SHELL32-MAIN)
66
67typedef struct
68{ LPCSTR szApp;
69 LPCSTR szOtherStuff;
70 HICON hIcon;
71} ABOUT_INFO;
72
73#define IDC_STATIC_TEXT 100
74#define IDC_LISTBOX 99
75#define IDC_WINE_TEXT 98
76#define IDC_ODIN_TEXT 98
77
78#define DROP_FIELD_TOP (-15)
79#define DROP_FIELD_HEIGHT 15
80
81extern HICON hIconTitleFont;
82
83static BOOL __get_dropline( HWND hWnd, LPRECT lprect )
84{ HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT);
85 if( hWndCtl )
86 { GetWindowRect( hWndCtl, lprect );
87 MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 );
88 lprect->bottom = (lprect->top += DROP_FIELD_TOP);
89 return TRUE;
90 }
91 return FALSE;
92}
93
94
95/*************************************************************************
96 * AboutDlgProc32 (internal)
97 */
98#define IDC_ODINLOGO 2001
99#define IDC_ODINBUILDNR 2002
100#define IDB_ODINLOGO 5555
101
102BOOL WINAPI AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
103 LPARAM lParam )
104{
105 HWND hWndCtl;
106 char Template[512], AppTitle[512];
107
108 switch(msg)
109 {
110 case WM_INITDIALOG:
111 {
112 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
113 if(info)
114 {
115 const char* const *pstr = SHELL_People;
116
117 SendDlgItemMessageA(hWnd, stc1, STM_SETICON,info->hIcon, 0);
118 GetWindowTextA( hWnd, Template, sizeof(Template) );
119 sprintf( AppTitle, Template, info->szApp );
120 SetWindowTextA( hWnd, AppTitle );
121 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT), info->szOtherStuff );
122
123 sprintf( AppTitle, "(%s)", __DATE__);
124 SetWindowTextA( GetDlgItem(hWnd, IDC_ODINBUILDNR), AppTitle);
125 HWND hwndOdinLogo = GetDlgItem(hWnd, IDC_ODINLOGO);
126 if(hwndOdinLogo) {
127 HBITMAP hBitmap = LoadBitmapA(shell32_hInstance, MAKEINTRESOURCEA(IDB_ODINLOGO));
128 SendMessageA(hwndOdinLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
129 }
130
131 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
132 SendMessageA( hWndCtl, WM_SETREDRAW, 0, 0 );
133#if 0 //CB: not used (hIconTitleFont not valid!!!), default font is ok
134 SendMessageA( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
135#endif
136 while (*pstr)
137 {
138 SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)*pstr );
139 pstr++;
140 }
141 SendMessageA( hWndCtl, WM_SETREDRAW, 1, 0 );
142 }
143 return 1;
144 }
145
146 case WM_PAINT:
147 {
148 RECT rect;
149 PAINTSTRUCT ps;
150 HDC hDC = BeginPaint( hWnd, &ps );
151
152 if( __get_dropline( hWnd, &rect ) ) {
153 SelectObject( hDC, GetStockObject( BLACK_PEN ) );
154 MoveToEx( hDC, rect.left, rect.top, NULL );
155 LineTo( hDC, rect.right, rect.bottom );
156 }
157 EndPaint( hWnd, &ps );
158 break;
159 }
160
161 case WM_LBTRACKPOINT:
162 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
163 if( (INT)GetKeyState( VK_CONTROL ) < 0 )
164 { if( DragDetect( hWndCtl, *((LPPOINT)&lParam) ) )
165 { INT idx = SendMessageA( hWndCtl, LB_GETCURSEL, 0, 0 );
166 if( idx != -1 )
167 { INT length = SendMessageA( hWndCtl, LB_GETTEXTLEN, (WPARAM)idx, 0 );
168 HGLOBAL hMemObj = GlobalAlloc( GMEM_MOVEABLE, length + 1 );
169 char* pstr = (char*)GlobalLock( hMemObj );
170
171 if( pstr )
172 { HCURSOR hCursor = LoadCursorA( 0, (LPCSTR)OCR_DRAGOBJECT );
173 SendMessageA( hWndCtl, LB_GETTEXT, (WPARAM)idx, (LPARAM)pstr );
174 SendMessageA( hWndCtl, LB_DELETESTRING, (WPARAM)idx, 0 );
175 UpdateWindow( hWndCtl );
176
177 if( !DragObject(hWnd, hWnd, DRAGOBJ_DATA, hMemObj, hCursor) )
178 SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)pstr );
179 }
180 if( hMemObj )
181 GlobalFree( hMemObj );
182 }
183 }
184 }
185 break;
186
187 case WM_QUERYDROPOBJECT:
188 if( wParam == 0 )
189 { LPDRAGINFO lpDragInfo = (LPDRAGINFO)lParam;
190 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
191 { RECT rect;
192 if( __get_dropline( hWnd, &rect ) )
193 { POINT pt;
194 pt.x=lpDragInfo->pt.x;
195 pt.x=lpDragInfo->pt.y;
196 rect.bottom += DROP_FIELD_HEIGHT;
197 if( PtInRect( &rect, pt ) )
198 { SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
199 return TRUE;
200 }
201 }
202 }
203 }
204 break;
205
206 case WM_DROPOBJECT:
207 if( wParam == hWnd )
208 { LPDRAGINFO lpDragInfo = (LPDRAGINFO)lParam;
209 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
210 { char* pstr = (char*)GlobalLock( (HGLOBAL)(lpDragInfo->hList) );
211 if( pstr )
212 { static char __appendix_str[] = " with";
213
214 hWndCtl = GetDlgItem( hWnd, IDC_ODIN_TEXT );
215 SendMessageA( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
216 if( !strncmp( Template, "ODIN", 4 ) )
217 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT), Template );
218 else
219 { char* pch = Template + strlen(Template) - strlen(__appendix_str);
220 *pch = '\0';
221 SendMessageA( GetDlgItem(hWnd, IDC_LISTBOX), LB_ADDSTRING,
222 (WPARAM)-1, (LPARAM)Template );
223 }
224
225 strcpy( Template, pstr );
226 strcat( Template, __appendix_str );
227 SetWindowTextA( hWndCtl, Template );
228 SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
229 return TRUE;
230 }
231 }
232 }
233 break;
234
235 case WM_COMMAND:
236 if (wParam == IDOK)
237 {
238 EndDialog(hWnd, TRUE);
239 return TRUE;
240 }
241 break;
242
243 case WM_CLOSE:
244 EndDialog(hWnd, TRUE);
245 break;
246 }
247 return 0;
248}
249
250
251/*************************************************************************
252 * ShellAboutA [SHELL32.243]
253 */
254
255BOOL WIN32API ShellAboutA(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
256 HICON hIcon )
257{ ABOUT_INFO info;
258 HRSRC hRes;
259 LPVOID dlgTemplate;
260
261 if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
262 return FALSE;
263 if(!(dlgTemplate = (LPVOID)LoadResource(shell32_hInstance, hRes)))
264 return FALSE;
265
266 info.szApp = szApp;
267 info.szOtherStuff = szOtherStuff;
268 info.hIcon = hIcon;
269 if (!hIcon) info.hIcon = LoadIconA( 0, MAKEINTRESOURCEA(OIC_ODINICON) );
270 return DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
271 (DLGTEMPLATE*)dlgTemplate , hWnd, AboutDlgProc, (LPARAM)&info );
272}
273
274
275/*************************************************************************
276 * ShellAboutW [SHELL32.244]
277 */
278BOOL WIN32API ShellAboutW(HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
279 HICON hIcon )
280{ INT ret;
281 ABOUT_INFO info;
282 HRSRC hRes;
283 LPVOID dlgTemplate;
284
285 if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
286 return FALSE;
287 if(!(dlgTemplate = (LPVOID)LoadResource(shell32_hInstance, hRes)))
288 return FALSE;
289
290 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
291 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
292 info.hIcon = hIcon;
293 if (!hIcon) info.hIcon = LoadIconA( 0, MAKEINTRESOURCEA(OIC_ODINICON) );
294 ret = DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
295 (DLGTEMPLATE*)dlgTemplate, hWnd, AboutDlgProc, (LPARAM)&info );
296 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
297 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
298 return ret;
299}
300
301/*************************************************************************
302 * ExtractAssociatedIcon [SHELL.36]
303 *
304 * Return icon for given file (either from file itself or from associated
305 * executable) and patch parameters if needed.
306 */
307HICON WIN32API ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath,
308 LPWORD lpiIcon)
309{
310 HICON hIcon;
311
312 hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon);
313
314 if( hIcon < 2 )
315 { if( hIcon == 1 ) /* no icons found in given file */
316 { char tempPath[0x104];
317 UINT uRet = FindExecutableA(lpIconPath,NULL,tempPath);
318
319 if( uRet > 32 && tempPath[0] )
320 { strcpy(lpIconPath,tempPath);
321 hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon);
322 if( hIcon > 2 )
323 return hIcon;
324 }
325 else hIcon = 0;
326 }
327
328 if( hIcon == 1 )
329 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
330 else
331 *lpiIcon = 6; /* generic icon - found nothing */
332
333 GetModuleFileNameA(hInst, lpIconPath, 0x80);
334 hIcon = LoadIconA( hInst, (LPCSTR)*lpiIcon);
335 }
336 return hIcon;
337}
338
339#if 0 //CB: DirectResAlloc16 not yet ported
340/*************************************************************************
341 * SHELL_LoadResource
342 */
343static HGLOBAL SHELL_LoadResource(HINSTANCE hInst, HFILE hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
344{ BYTE* ptr;
345 HGLOBAL handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
346
347 TRACE("\n");
348
349 if( (ptr = (BYTE*)GlobalLock( handle )) )
350 { _llseek( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
351 _lread( hFile, (char*)ptr, pNInfo->length << sizeShift);
352 return handle;
353 }
354 return 0;
355}
356
357/*************************************************************************
358 * ICO_LoadIcon
359 */
360static HGLOBAL ICO_LoadIcon(HINSTANCE hInst, HFILE hFile, LPicoICONDIRENTRY lpiIDE)
361{ BYTE* ptr;
362 HGLOBAL handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
363 TRACE("\n");
364 if( (ptr = (BYTE*)GlobalLock( handle )) )
365 { _llseek( hFile, lpiIDE->dwImageOffset, SEEK_SET);
366 _lread( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
367 return handle;
368 }
369 return 0;
370}
371
372/*************************************************************************
373 * ICO_GetIconDirectory
374 *
375 * Read .ico file and build phony ICONDIR struct for GetIconID
376 */
377static HGLOBAL ICO_GetIconDirectory(HINSTANCE hInst, HFILE hFile, LPicoICONDIR* lplpiID )
378{ WORD id[3]; /* idReserved, idType, idCount */
379 LPicoICONDIR lpiID;
380 int i;
381
382 TRACE("\n");
383 _llseek( hFile, 0, SEEK_SET );
384 if( _lread(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
385
386 /* check .ICO header
387 *
388 * - see http://www.microsoft.com/win32dev/ui/icons.htm
389 */
390
391 if( id[0] || id[1] != 1 || !id[2] ) return 0;
392
393 i = id[2]*sizeof(icoICONDIRENTRY) ;
394
395 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i + sizeof(id));
396
397 if( _lread(hFile,(char*)lpiID->idEntries,i) == i )
398 { HGLOBAL handle = DirectResAlloc( hInst, 0x10,
399 id[2]*sizeof(CURSORICONDIRENTRY) + sizeof(id) );
400 if( handle )
401 { CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock( handle );
402 lpID->idReserved = lpiID->idReserved = id[0];
403 lpID->idType = lpiID->idType = id[1];
404 lpID->idCount = lpiID->idCount = id[2];
405 for( i=0; i < lpiID->idCount; i++ )
406 { memcpy((void*)(lpID->idEntries + i),
407 (void*)(lpiID->idEntries + i), sizeof(CURSORICONDIRENTRY) - 2);
408 lpID->idEntries[i].wResId = i;
409 }
410 *lplpiID = lpiID;
411 return handle;
412 }
413 }
414 /* fail */
415
416 HeapFree( GetProcessHeap(), 0, lpiID);
417 return 0;
418}
419#endif
420
421//iconcache.c
422DWORD SHELL_GetResourceTable(HFILE hFile, LPBYTE *retptr);
423
424//CB: from loader/pe_resource.c
425
426/**********************************************************************
427 * GetResDirEntryW
428 *
429 * Helper function - goes down one level of PE resource tree
430 *
431 */
432PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY resdirptr,
433 LPCWSTR name,DWORD root,
434 BOOL allowdefault)
435{
436 int entrynum;
437 PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
438 int namelen;
439
440 if (HIWORD(name)) {
441 if (name[0]=='#') {
442 char buf[10];
443
444 lstrcpynWtoA(buf,name+1,10);
445 return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault);
446 }
447 entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
448 (BYTE *) resdirptr +
449 sizeof(IMAGE_RESOURCE_DIRECTORY));
450 namelen = lstrlenW(name);
451 for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
452 {
453 PIMAGE_RESOURCE_DIR_STRING_U str =
454 (PIMAGE_RESOURCE_DIR_STRING_U) (root +
455 entryTable[entrynum].u1.s.NameOffset);
456 if(namelen != str->Length)
457 continue;
458 if(lstrncmpiW(name,str->NameString,str->Length)==0)
459 return (PIMAGE_RESOURCE_DIRECTORY) (
460 root +
461 entryTable[entrynum].u2.s.OffsetToDirectory);
462 }
463 return NULL;
464 } else {
465 entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
466 (BYTE *) resdirptr +
467 sizeof(IMAGE_RESOURCE_DIRECTORY) +
468 resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
469 for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
470 if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
471 return (PIMAGE_RESOURCE_DIRECTORY) (
472 root +
473 entryTable[entrynum].u2.s.OffsetToDirectory);
474 /* just use first entry if no default can be found */
475 if (allowdefault && !name && resdirptr->NumberOfIdEntries)
476 return (PIMAGE_RESOURCE_DIRECTORY) (
477 root +
478 entryTable[0].u2.s.OffsetToDirectory);
479 return NULL;
480 }
481}
482
483/*************************************************************************
484 * InternalExtractIcon [SHELL.39]
485 *
486 * This abortion is called directly by Progman
487 */
488HGLOBAL WINAPI InternalExtractIcon(HINSTANCE hInstance,
489 LPCSTR lpszExeFileName, UINT nIconIndex, WORD n )
490{ HGLOBAL hRet = 0;
491 HGLOBAL* RetPtr = NULL;
492 LPBYTE pData;
493 OFSTRUCT ofs;
494 DWORD sig;
495 HFILE hFile = OpenFile( lpszExeFileName, &ofs, OF_READ );
496 UINT iconDirCount = 0,iconCount = 0;
497 LPBYTE peimage;
498 HANDLE fmapping;
499
500 TRACE("(%04x,file %s,start %d,extract %d\n",
501 hInstance, lpszExeFileName, nIconIndex, n);
502
503 if( hFile == HFILE_ERROR || !n )
504 return 0;
505
506 hRet = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
507 RetPtr = (HGLOBAL*)GlobalLock(hRet);
508
509 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
510
511 sig = SHELL_GetResourceTable(hFile,&pData);
512#if 0 //CB: some functions not (yet) supported
513 if( sig==IMAGE_OS2_SIGNATURE || sig==1 ) /* .ICO file */
514 { HICON hIcon = 0;
515 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
516 NE_NAMEINFO* pIconStorage = NULL;
517 NE_NAMEINFO* pIconDir = NULL;
518 LPicoICONDIR lpiID = NULL;
519
520 if( pData == (BYTE*)-1 )
521 { hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID); /* check for .ICO file */
522 if( hIcon )
523 { iconDirCount = 1; iconCount = lpiID->idCount;
524 }
525 }
526 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
527 { if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON ) /* find icon directory and icon repository */
528 { iconDirCount = pTInfo->count;
529 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
530 TRACE("\tfound directory - %i icon families\n", iconDirCount);
531 }
532 if( pTInfo->type_id == NE_RSCTYPE_ICON )
533 { iconCount = pTInfo->count;
534 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
535 TRACE("\ttotal icons - %i\n", iconCount);
536 }
537 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
538 }
539
540 /* load resources and create icons */
541
542 if( (pIconStorage && pIconDir) || lpiID )
543 { if( nIconIndex == (UINT16)-1 )
544 { RetPtr[0] = iconDirCount;
545 }
546 else if( nIconIndex < iconDirCount )
547 { UINT i, icon;
548 if( n > iconDirCount - nIconIndex )
549 n = iconDirCount - nIconIndex;
550
551 for( i = nIconIndex; i < nIconIndex + n; i++ )
552 { /* .ICO files have only one icon directory */
553
554 if( lpiID == NULL )
555 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i, *(WORD*)pData );
556 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
557 GlobalFree(hIcon);
558 }
559
560 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
561 { hIcon = 0;
562 if( lpiID )
563 { hIcon = ICO_LoadIcon( hInstance, hFile, lpiID->idEntries + RetPtr[icon-nIconIndex]);
564 }
565 else
566 { for( i = 0; i < iconCount; i++ )
567 { if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
568 { hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,*(WORD*)pData );
569 }
570 }
571 }
572 if( hIcon )
573 { RetPtr[icon-nIconIndex] = LoadIconHandler16( hIcon, TRUE );
574 FarSetOwner16( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
575 }
576 else
577 { RetPtr[icon-nIconIndex] = 0;
578 }
579 }
580 }
581 }
582 if( lpiID )
583 HeapFree( GetProcessHeap(), 0, lpiID);
584 else
585 HeapFree( GetProcessHeap(), 0, pData);
586 }
587#endif
588 if( sig == IMAGE_NT_SIGNATURE)
589 { LPBYTE idata,igdata;
590 PIMAGE_DOS_HEADER dheader;
591 PIMAGE_NT_HEADERS pe_header;
592 PIMAGE_SECTION_HEADER pe_sections;
593 PIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
594 PIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
595 int i,j;
596 PIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
597 CURSORICONDIR **cids;
598
599 fmapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
600 if (fmapping == 0)
601 { /* FIXME, INVALID_HANDLE_VALUE? */
602 WARN("failed to create filemap.\n");
603 hRet = 0;
604 goto end_2; /* failure */
605 }
606 peimage = (BYTE*)MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
607 if (!peimage)
608 { WARN("failed to mmap filemap.\n");
609 hRet = 0;
610 goto end_2; /* failure */
611 }
612 dheader = (PIMAGE_DOS_HEADER)peimage;
613
614 /* it is a pe header, SHELL_GetResourceTable checked that */
615 pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
616
617 /* probably makes problems with short PE headers... but I haven't seen
618 * one yet...
619 */
620 pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
621 rootresdir = NULL;
622
623 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++)
624 { if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
625 continue;
626 /* FIXME: doesn't work when the resources are not in a seperate section */
627 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)
628 { rootresdir = (PIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
629 break;
630 }
631 }
632
633 if (!rootresdir)
634 { WARN("haven't found section for resource directory.\n");
635 goto end_4; /* failure */
636 }
637
638 icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICONW, (DWORD)rootresdir,FALSE);
639
640 if (!icongroupresdir)
641 { WARN("No Icongroupresourcedirectory!\n");
642 goto end_4; /* failure */
643 }
644
645 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
646
647 if( nIconIndex == (UINT)-1 )
648 { RetPtr[0] = iconDirCount;
649 goto end_3; /* success */
650 }
651
652 if (nIconIndex >= iconDirCount)
653 { WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
654 GlobalFree(hRet);
655 goto end_4; /* failure */
656 }
657
658 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
659
660 /* caller just wanted the number of entries */
661 xresent = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
662
663 /* assure we don't get too much ... */
664 if( n > iconDirCount - nIconIndex )
665 { n = iconDirCount - nIconIndex;
666 }
667
668 /* starting from specified index ... */
669 xresent = xresent+nIconIndex;
670
671 for (i=0;i<n;i++,xresent++)
672 { CURSORICONDIR *cid;
673 PIMAGE_RESOURCE_DIRECTORY resdir;
674
675 /* go down this resource entry, name */
676 resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
677
678 /* default language (0) */
679 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
680 igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir;
681
682 /* lookup address in mapped image for virtual address */
683 igdata = NULL;
684
685 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
686 { if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
687 continue;
688 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
689 continue;
690 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
691 }
692
693 if (!igdata)
694 { WARN("no matching real address for icongroup!\n");
695 goto end_4; /* failure */
696 }
697 /* found */
698 cid = (CURSORICONDIR*)igdata;
699 cids[i] = cid;
700 RetPtr[i] = LookupIconIdFromDirectoryEx(igdata,TRUE,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0);
701 }
702
703 iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,(DWORD)rootresdir,FALSE);
704
705 if (!iconresdir)
706 { WARN("No Iconresourcedirectory!\n");
707 goto end_4; /* failure */
708 }
709
710 for (i=0;i<n;i++)
711 { PIMAGE_RESOURCE_DIRECTORY xresdir;
712 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],(DWORD)rootresdir,FALSE);
713 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
714 idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir;
715 idata = NULL;
716
717 /* map virtual to address in image */
718 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
719 { if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
720 continue;
721 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
722 continue;
723 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
724 }
725 if (!idata)
726 { WARN("no matching real address found for icondata!\n");
727 RetPtr[i]=0;
728 continue;
729 }
730 RetPtr[i] = CreateIconFromResourceEx(idata,idataent->Size,TRUE,0x00030000,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0);
731 }
732 goto end_3; /* sucess */
733 }
734 goto end_1; /* return array with icon handles */
735
736/* cleaning up (try & catch would be nicer) */
737end_4: hRet = 0; /* failure */
738end_3: UnmapViewOfFile(peimage); /* success */
739end_2: CloseHandle(fmapping);
740end_1: _lclose( hFile);
741 return hRet;
742}
743
744/*************************************************************************
745 * SHELL_GetResourceTable
746 */
747DWORD SHELL_GetResourceTable(HFILE hFile,LPBYTE *retptr)
748{ IMAGE_DOS_HEADER mz_header;
749 char magic[4];
750 int size;
751
752 TRACE("\n");
753
754 *retptr = NULL;
755 _llseek( hFile, 0, SEEK_SET );
756 if ((_lread(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) || (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
757 { /* .ICO file ? */
758 if (mz_header.e_cblp == 1)
759 { /* ICONHEADER.idType, must be 1 */
760 *retptr = (LPBYTE)-1;
761 return 1;
762 }
763 else
764 return 0; /* failed */
765 }
766 _llseek( hFile, mz_header.e_lfanew, SEEK_SET );
767
768 if (_lread( hFile, magic, sizeof(magic) ) != sizeof(magic))
769 return 0;
770
771 _llseek( hFile, mz_header.e_lfanew, SEEK_SET);
772
773 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
774 return IMAGE_NT_SIGNATURE;
775
776 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE)
777 { IMAGE_OS2_HEADER ne_header;
778 LPBYTE pTypeInfo = (LPBYTE)-1;
779
780 if (_lread(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
781 return 0;
782
783 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE)
784 return 0;
785
786 size = ne_header.ne_restab - ne_header.ne_rsrctab;
787
788 if( size > sizeof(NE_TYPEINFO) )
789 { pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
790 if( pTypeInfo )
791 { _llseek(hFile, mz_header.e_lfanew+ne_header.ne_rsrctab, SEEK_SET);
792 if( _lread( hFile, (char*)pTypeInfo, size) != size )
793 { HeapFree( GetProcessHeap(), 0, pTypeInfo);
794 pTypeInfo = NULL;
795 }
796 }
797 }
798 *retptr = pTypeInfo;
799 return IMAGE_OS2_SIGNATURE;
800 }
801 return 0; /* failed */
802}
803
804/*************************************************************************
805 * SHELL_FindExecutable [Internal]
806 *
807 * Utility for code sharing between FindExecutable and ShellExecute
808 */
809HINSTANCE SHELL_FindExecutable( LPCSTR lpFile,
810 LPCSTR lpOperation,
811 LPSTR lpResult)
812{ char *extension = NULL; /* pointer to file extension */
813 char tmpext[5]; /* local copy to mung as we please */
814 char filetype[256]; /* registry name for this filetype */
815 LONG filetypelen=256; /* length of above */
816 char command[256]; /* command from registry */
817 LONG commandlen=256; /* This is the most DOS can handle :) */
818 char buffer[256]; /* Used to GetProfileString */
819 HINSTANCE retval=31; /* default - 'No association was found' */
820 char *tok; /* token pointer */
821 int i; /* random counter */
822 char xlpFile[256]; /* result of SearchPath */
823
824 dprintf(("SHELL32:SHELL:SHELL_FindExecutable(%s,%s,%08xh)\n",
825 lpFile,
826 lpOperation,
827 lpResult));
828
829 lpResult[0]='\0'; /* Start off with an empty return string */
830
831 /* trap NULL parameters on entry */
832 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
833 { dprintf(("SHELL32:SHELL:SHELL_FindExecutable(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n",
834 lpFile, lpOperation, lpResult));
835 return 2; /* File not found. Close enough, I guess. */
836 }
837
838 if (SearchPathA( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
839 { dprintf(("SHELL32:SHELL:SHELL_FindExecutable(SearchPath32A returned non-zero\n"));
840 lpFile = xlpFile;
841 }
842
843 /* First thing we need is the file's extension */
844 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
845 /* File->Run in progman uses */
846 /* .\FILE.EXE :( */
847 dprintf(("SHELL32:SHELL:SHELL_FindExecutable(xlpFile=%s,extension=%s)\n",
848 xlpFile, extension));
849
850 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
851 { dprintf(("SHELL32:SHELL:SHELL_FindExecutable Returning 31 - No association\n"));
852 return 31; /* no association */
853 }
854
855 /* Make local copy & lowercase it for reg & 'programs=' lookup */
856 lstrcpynA( tmpext, extension, 5 );
857 CharLowerA( tmpext );
858
859
860 dprintf(("SHELL32:SHELL:SHELL_FindExecutable(%s file)\n", tmpext));
861
862 /* Three places to check: */
863 /* 1. win.ini, [windows], programs (NB no leading '.') */
864 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
865 /* 3. win.ini, [extensions], extension (NB no leading '.' */
866 /* All I know of the order is that registry is checked before */
867 /* extensions; however, it'd make sense to check the programs */
868 /* section first, so that's what happens here. */
869
870 /* See if it's a program - if GetProfileString fails, we skip this
871 * section. Actually, if GetProfileString fails, we've probably
872 * got a lot more to worry about than running a program... */
873 if ( GetProfileStringA("windows", "programs", "exe pif bat com",
874 buffer, sizeof(buffer)) > 0 )
875 { for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
876
877 tok = strtok(buffer, " \t"); /* ? */
878 while( tok!= NULL)
879 {
880 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
881 {
882 strcpy(lpResult, xlpFile);
883 /* Need to perhaps check that the file has a path
884 * attached */
885 dprintf(("SHELL32:SHELL:SHELL_FindExecutable found %s\n",
886 lpResult));
887 return 33;
888
889 /* Greater than 32 to indicate success FIXME According to the
890 * docs, I should be returning a handle for the
891 * executable. Does this mean I'm supposed to open the
892 * executable file or something? More RTFM, I guess... */
893 }
894 tok=strtok(NULL, " \t");
895 }
896 }
897
898 /* Check registry */
899 if (RegQueryValueA( HKEY_CLASSES_ROOT, tmpext, filetype,
900 &filetypelen ) == ERROR_SUCCESS )
901 {
902 filetype[filetypelen]='\0';
903 dprintf(("SHELL32:SHELL:SHELL_FindExecutable(File type: %s)\n",
904 filetype));
905
906 /* Looking for ...buffer\shell\lpOperation\command */
907 strcat( filetype, "\\shell\\" );
908 strcat( filetype, lpOperation );
909 strcat( filetype, "\\command" );
910
911 if (RegQueryValueA( HKEY_CLASSES_ROOT, filetype, command,
912 &commandlen ) == ERROR_SUCCESS )
913 {
914 LPSTR tmp;
915 char param[256];
916 LONG paramlen = 256;
917
918 /* Get the parameters needed by the application
919 from the associated ddeexec key */
920 tmp = strstr(filetype,"command");
921 tmp[0] = '\0';
922 strcat(filetype,"ddeexec");
923
924 if(RegQueryValueA( HKEY_CLASSES_ROOT, filetype, param,&paramlen ) == ERROR_SUCCESS)
925 {
926 strcat(command," ");
927 strcat(command,param);
928 commandlen += paramlen;
929 }
930
931 /* Is there a replace() function anywhere? */
932 command[commandlen]='\0';
933 strcpy( lpResult, command );
934 tok=strstr( lpResult, "%1" );
935 if (tok != NULL)
936 {
937 tok[0]='\0'; /* truncate string at the percent */
938 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
939 tok=strstr( command, "%1" );
940 if ((tok!=NULL) && (strlen(tok)>2))
941 {
942 strcat( lpResult, &tok[2] );
943 }
944 }
945 retval=33; /* FIXME see above */
946 }
947 }
948 else /* Check win.ini */
949 {
950 /* Toss the leading dot */
951 extension++;
952 if ( GetProfileStringA( "extensions", extension, "", command,
953 sizeof(command)) > 0)
954 {
955 if (strlen(command)!=0)
956 {
957 strcpy( lpResult, command );
958 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
959 if (tok != NULL)
960 {
961 tok[0]='\0';
962 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
963 tok=strstr( command, "^" ); /* see above */
964 if ((tok != NULL) && (strlen(tok)>5))
965 {
966 strcat( lpResult, &tok[5]);
967 }
968 }
969 retval=33; /* FIXME - see above */
970 }
971 }
972 }
973
974 dprintf(("SHELL32:SHELL:SHELL_FindExecutable (returning %s)\n", lpResult));
975 return retval;
976}
977
978/*************************************************************************
979 * ShellExecuteA [SHELL32.245]
980 */
981
982HINSTANCE WIN32API ShellExecuteA(HWND hWnd, LPCSTR lpOperation,
983 LPCSTR lpFile,
984 LPCSTR lpParameters,
985 LPCSTR lpDirectory,
986 INT iShowCmd )
987{
988 HINSTANCE retval=31;
989 char old_dir[1024];
990 char cmd[256];
991 LONG cmdlen = sizeof( cmd );
992 LPSTR tok;
993
994 if (lpFile==NULL)
995 return 0; /* should not happen */
996
997 if (lpOperation==NULL) /* default is open */
998 lpOperation="open";
999
1000 if (lpDirectory)
1001 {
1002 // @@@PH 2002-02-26 might throw whole process off track
1003 // in case of concurrency
1004 GetCurrentDirectoryA( sizeof(old_dir), old_dir );
1005 SetCurrentDirectoryA( lpDirectory );
1006 }
1007
1008 cmd[0] = '\0';
1009 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
1010
1011 if (retval > 32) /* Found */
1012 {
1013 if (lpParameters)
1014 {
1015 strcat(cmd," ");
1016 strcat(cmd,lpParameters);
1017 }
1018
1019 dprintf(("starting %s\n",cmd));
1020 retval = WinExec( cmd, iShowCmd );
1021 }
1022 else
1023 {
1024 // - path might be an URL
1025 // - argument might be associated with some class / app
1026
1027 // 2002-02-26 PH
1028 // File Extension Association is missing. We'd have to lookup
1029 // i. e. ".doc" and create the command.
1030 // @@@PH
1031
1032 // build lookup key
1033 char lpstrShellSubkey[256] = "\\shell\\";
1034 /* Looking for ...protocol\shell\lpOperation\command */
1035 strcat( lpstrShellSubkey, lpOperation );
1036 strcat( lpstrShellSubkey, "\\command" );
1037
1038 // First, check for URL association
1039 if(PathIsURLA((LPSTR)lpFile)) /* File not found, check for URL */
1040 {
1041 LPSTR lpstrRes;
1042 INT iSize;
1043
1044 lpstrRes = strchr(lpFile,':');
1045 if (NULL != lpstrRes)
1046 {
1047 char szProtocol[256];
1048
1049 iSize = lpstrRes - lpFile;
1050
1051 strncpy(szProtocol,
1052 lpFile,
1053 min( sizeof( szProtocol ), iSize) );
1054
1055 /* Remove File Protocol from lpFile */
1056 /* In the case file://path/file */
1057 if(!strnicmp(lpFile,"file",iSize))
1058 {
1059 lpFile += iSize;
1060 while(*lpFile == ':') lpFile++;
1061 }
1062
1063 /* Get the application for the protocol and execute it */
1064 if (RegQueryValueA(HKEY_CLASSES_ROOT,
1065 szProtocol,
1066 cmd,
1067 &cmdlen ) == ERROR_SUCCESS )
1068 {
1069 LPSTR tmp;
1070 char param[256] = "";
1071 LONG paramlen = 256;
1072
1073 /* Get the parameters needed by the application
1074 from the associated ddeexec key */
1075 tmp = strstr(szProtocol,"command");
1076 tmp[0] = '\0';
1077 strcat(szProtocol,"ddeexec");
1078
1079 if(RegQueryValueA(HKEY_CLASSES_ROOT,
1080 szProtocol,
1081 param,
1082 &paramlen ) == ERROR_SUCCESS)
1083 {
1084 strcat(cmd," ");
1085 strcat(cmd,param);
1086 cmdlen += paramlen;
1087 }
1088 }
1089 }
1090 }
1091
1092
1093 // Second, check for filename extension association
1094 if (0 == cmd[0])
1095 {
1096 LPSTR lpstrRDot = strrchr(lpFile, '.');
1097 if (NULL != lpstrRDot)
1098 {
1099 char szAssociation[256];
1100 LONG lAssociationLen = sizeof( szAssociation );
1101
1102 // lookup associated application (or COM object) for
1103 // this extension
1104 if (RegQueryValueA(HKEY_CLASSES_ROOT,
1105 lpstrRDot,
1106 szAssociation,
1107 &lAssociationLen) == ERROR_SUCCESS)
1108 {
1109 // append the shell subkey
1110 strcat(szAssociation, lpstrShellSubkey);
1111 lAssociationLen = sizeof( szAssociation );
1112
1113 // lookup application for retrieved association
1114 if (RegQueryValueA(HKEY_CLASSES_ROOT,
1115 szAssociation,
1116 cmd,
1117 &cmdlen) == ERROR_SUCCESS)
1118 {
1119 // received cmd now
1120 }
1121 }
1122 }
1123 }
1124
1125
1126#ifdef __WIN32OS2__
1127 if (0 == cmd[0])
1128 {
1129 // OS/2 specific addon:
1130 // if no windows association is found, pass on to the workplace shell
1131 // eventually.
1132 retval = ShellExecuteOS2(hWnd,
1133 lpOperation,
1134 lpFile,
1135 lpParameters,
1136 lpDirectory,
1137 iShowCmd);
1138 }
1139#endif
1140
1141 if (0 != cmd[0])
1142 {
1143 // resolve the parameters
1144 // @@@PH 2002-02-26 there might be more than one parameter only
1145 /* Is there a replace() function anywhere? */
1146 tok=strstr( cmd, "%1" );
1147 if (tok != NULL)
1148 {
1149 tok[0]='\0'; /* truncate string at the percent */
1150 strcat( cmd, lpFile ); /* what if no dir in xlpFile? */
1151 tok=strstr( cmd, "%1" );
1152 if ((tok!=NULL) && (strlen(tok)>2))
1153 {
1154 strcat( cmd, &tok[2] );
1155 }
1156 }
1157 }
1158
1159 /* Nothing was done yet, try to execute the cmdline directly,
1160 maybe it's an OS/2 program */
1161 if (0 == cmd[0])
1162 {
1163 strcpy(cmd,lpFile);
1164 strcat(cmd,lpParameters ? lpParameters : "");
1165 }
1166
1167 // now launch ... something :)
1168 retval = WinExec( cmd, iShowCmd );
1169 }
1170
1171 if (lpDirectory)
1172 SetCurrentDirectoryA( old_dir );
1173
1174 return retval;
1175}
1176
1177
1178/*****************************************************************************
1179 * Name : UINT DragQueryFileAorW
1180 * Purpose :
1181 * Parameters: HDROP hDrop - drop structure handle
1182 * UINT iFile - index of file to query
1183 * LPTSTR lpszFile - target buffer
1184 * UINT cch - target buffer size
1185 * Variables :
1186 * Result :
1187 * Remark :
1188 * Status : UNTESTED STUB
1189 *
1190 * Author : Patrick Haller [Tue, 1999/06/09 20:00]
1191 *****************************************************************************/
1192
1193UINT WIN32API DragQueryFileAorW(HDROP hDrop, UINT iFile, LPTSTR lpszFile,
1194 UINT cch)
1195{
1196 // @@@PH maybe they want automatic determination here
1197 if (SHELL_OsIsUnicode())
1198 return DragQueryFileW(hDrop, iFile, (LPWSTR)lpszFile, cch);
1199 else
1200 return DragQueryFileA(hDrop, iFile, lpszFile, cch);
1201}
1202
1203
1204LPCSTR debugstr_guid1( void *id1 )
1205{
1206 static char str[40];
1207 GUID *id = (GUID *)id1;
1208
1209 if (!id) return "(null)";
1210 if (!HIWORD(id))
1211 {
1212 sprintf( str, "<guid-0x%04x>", LOWORD(id) );
1213 }
1214 else
1215 {
1216 sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1217 id->Data1, id->Data2, id->Data3,
1218 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
1219 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
1220 }
1221 return str;
1222}
1223
Note: See TracBrowser for help on using the repository browser.