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

Last change on this file since 7904 was 7904, checked in by sandervl, 24 years ago

extended logging added

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