2 * Shell Library Functions
22 extern HANDLE
CURSORICON_LoadHandler( HANDLE
, HINSTANCE
, BOOL
);
23 extern WORD
GetIconID( HANDLE hResource
, DWORD resType
);
25 /*************************************************************************
26 * DragAcceptFiles [SHELL.9]
28 void DragAcceptFiles(HWND hWnd
, BOOL b
)
30 WND
* wnd
= WIN_FindWndPtr(hWnd
);
33 wnd
->dwExStyle
= b
? wnd
->dwExStyle
| WS_EX_ACCEPTFILES
34 : wnd
->dwExStyle
& ~WS_EX_ACCEPTFILES
;
38 /*************************************************************************
39 * DragQueryFile [SHELL.11]
41 UINT
DragQueryFile(HDROP16 hDrop
, WORD wFile
, LPSTR lpszFile
, WORD wLength
)
43 /* hDrop is a global memory block allocated with GMEM_SHARE
44 * with DROPFILESTRUCT as a header and filenames following
45 * it, zero length filename is in the end */
47 LPDROPFILESTRUCT lpDropFileStruct
;
51 dprintf_reg(stddeb
,"DragQueryFile(%04x, %i, %p, %u)\n",
52 hDrop
,wFile
,lpszFile
,wLength
);
54 lpDropFileStruct
= (LPDROPFILESTRUCT
) GlobalLock16(hDrop
);
57 dprintf_reg(stddeb
,"DragQueryFile: unable to lock handle!\n");
60 lpCurrent
= (LPSTR
) lpDropFileStruct
+ lpDropFileStruct
->wSize
;
65 while (*lpCurrent
++); /* skip filename */
67 return (wFile
== 0xFFFF) ? i
: 0;
70 i
= strlen(lpCurrent
);
71 if (!lpszFile
) return i
+1; /* needed buffer size */
73 i
= (wLength
> i
) ? i
: wLength
-1;
74 strncpy(lpszFile
, lpCurrent
, i
);
77 GlobalUnlock16(hDrop
);
82 /*************************************************************************
83 * DragFinish [SHELL.12]
85 void DragFinish(HDROP16 h
)
87 GlobalFree16((HGLOBAL16
)h
);
91 /*************************************************************************
92 * DragQueryPoint [SHELL.13]
94 BOOL
DragQueryPoint(HDROP16 hDrop
, POINT16
*p
)
96 LPDROPFILESTRUCT lpDropFileStruct
;
99 lpDropFileStruct
= (LPDROPFILESTRUCT
) GlobalLock16(hDrop
);
101 memcpy(p
,&lpDropFileStruct
->ptMousePos
,sizeof(POINT16
));
102 bRet
= lpDropFileStruct
->fInNonClientArea
;
104 GlobalUnlock16(hDrop
);
108 /*************************************************************************
109 * SHELL_FindExecutable
110 * Utility for code sharing between FindExecutable and ShellExecute
112 static HINSTANCE
SHELL_FindExecutable( LPCSTR lpFile
,
117 char *extension
= NULL
; /* pointer to file extension */
118 char tmpext
[5]; /* local copy to mung as we please */
119 char filetype
[256]; /* registry name for this filetype */
120 LONG filetypelen
=256; /* length of above */
121 char command
[256]; /* command from registry */
122 LONG commandlen
=256; /* This is the most DOS can handle :) */
123 char buffer
[256]; /* Used to GetProfileString */
124 HINSTANCE retval
=31; /* default - 'No association was found' */
125 char *tok
; /* token pointer */
126 int i
; /* random counter */
128 dprintf_exec(stddeb
, "SHELL_FindExecutable: File %s, Dir %s\n",
129 (lpFile
!= NULL
?lpFile
:"-"),
130 (lpDirectory
!= NULL
?lpDirectory
:"-"));
132 lpResult
[0]='\0'; /* Start off with an empty return string */
134 /* trap NULL parameters on entry */
135 if (( lpFile
== NULL
) || ( lpDirectory
== NULL
) ||
136 ( lpResult
== NULL
) || ( lpOperation
== NULL
))
138 /* FIXME - should throw a warning, perhaps! */
139 return 2; /* File not found. Close enough, I guess. */
142 /* First thing we need is the file's extension */
143 extension
= strchr( lpFile
, '.' ); /* Assumes first "." is the one... */
144 if ((extension
== NULL
) || (extension
== &lpFile
[strlen(lpFile
)]))
146 return 31; /* no association */
149 /* Make local copy & lowercase it for reg & 'programs=' lookup */
150 strncpy( tmpext
, extension
, 5 );
151 if (strlen(extension
)<=4)
152 tmpext
[strlen(extension
)]='\0';
155 for (i
=0;i
<strlen(tmpext
);i
++) tmpext
[i
]=tolower(tmpext
[i
]);
156 dprintf_exec(stddeb
, "SHELL_FindExecutable: %s file\n", tmpext
);
158 /* Three places to check: */
159 /* 1. win.ini, [windows], programs (NB no leading '.') */
160 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
161 /* 3. win.ini, [extensions], extension (NB no leading '.' */
162 /* All I know of the order is that registry is checked before */
163 /* extensions; however, it'd make sense to check the programs */
164 /* section first, so that's what happens here. */
166 /* See if it's a program */
167 GetProfileString("windows", "programs", "exe pif bat com",
168 buffer
, sizeof(buffer
)); /* FIXME check return code! */
170 for (i
=0;i
<strlen(buffer
); i
++) buffer
[i
]=tolower(buffer
[i
]);
172 tok
= strtok(buffer
, " \t"); /* ? */
175 if (strcmp(tok
, &tmpext
[1])==0) /* have to skip the leading "." */
177 strcpy(lpResult
, lpFile
); /* Need to perhaps check that */
178 /* the file has a path attached */
179 dprintf_exec(stddeb
, "SHELL_FindExecutable: found %s\n",
181 return 33; /* Greater than 32 to indicate success FIXME */
182 /* what are the correct values here? */
184 tok
=strtok(NULL
, " \t");
188 if (RegQueryValue16( (HKEY
)HKEY_CLASSES_ROOT
, tmpext
, filetype
,
189 &filetypelen
) == SHELL_ERROR_SUCCESS
)
191 filetype
[filetypelen
]='\0';
192 dprintf_exec(stddeb
, "SHELL_FindExecutable: File type: %s\n",
195 /* Looking for ...buffer\shell\lpOperation\command */
196 strcat( filetype
, "\\shell\\" );
197 strcat( filetype
, lpOperation
);
198 strcat( filetype
, "\\command" );
200 if (RegQueryValue16( (HKEY
)HKEY_CLASSES_ROOT
, filetype
, command
,
201 &commandlen
) == SHELL_ERROR_SUCCESS
)
203 /* Is there a replace() function anywhere? */
204 command
[commandlen
]='\0';
205 strcpy( lpResult
, command
);
206 tok
=strstr( lpResult
, "%1" );
209 tok
[0]='\0'; /* truncate string at the percent */
210 strcat( lpResult
, lpFile
); /* what if no dir in lpFile? */
211 tok
=strstr( command
, "%1" );
212 if ((tok
!=NULL
) && (strlen(tok
)>2))
214 strcat( lpResult
, &tok
[2] );
220 else /* Check win.ini */
222 /* Toss the leading dot */
224 GetProfileString( "extensions", extension
, "", command
,
226 if (strlen(command
)!=0)
228 strcpy( lpResult
, command
);
229 tok
=strstr( lpResult
, "^" ); /* should be ^.extension? */
233 strcat( lpResult
, lpFile
); /* what if no dir in lpFile? */
234 tok
=strstr( command
, "^" ); /* see above */
235 if ((tok
!= NULL
) && (strlen(tok
)>5))
237 strcat( lpResult
, &tok
[5]);
244 dprintf_exec(stddeb
, "SHELL_FindExecutable: returning %s\n", lpResult
);
248 /*************************************************************************
249 * ShellExecute [SHELL.20]
251 HINSTANCE
ShellExecute(HWND hWnd
, LPCSTR lpOperation
, LPCSTR lpFile
,
252 LPSTR lpParameters
, LPCSTR lpDirectory
,
258 dprintf_exec(stddeb
, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
259 hWnd
, lpOperation
? lpOperation
:"<null>", lpFile
? lpFile
:"<null>",
260 lpParameters
? lpParameters
: "<null>",
261 lpDirectory
? lpDirectory
: "<null>", iShowCmd
);
263 if (lpFile
==NULL
) return 0; /* should not happen */
264 if (lpOperation
==NULL
) /* default is open */
267 retval
= SHELL_FindExecutable( lpFile
, lpDirectory
, lpOperation
, cmd
);
277 strcat(cmd
,lpParameters
);
280 dprintf_exec(stddeb
,"ShellExecute:starting %s\n",cmd
);
281 return WinExec(cmd
,iShowCmd
);
284 /*************************************************************************
285 * FindExecutable [SHELL.21]
287 HINSTANCE
FindExecutable(LPCSTR lpFile
, LPCSTR lpDirectory
, LPSTR lpResult
)
289 HINSTANCE retval
=31; /* default - 'No association was found' */
291 dprintf_exec(stddeb
, "FindExecutable: File %s, Dir %s\n",
292 (lpFile
!= NULL
?lpFile
:"-"),
293 (lpDirectory
!= NULL
?lpDirectory
:"-"));
295 lpResult
[0]='\0'; /* Start off with an empty return string */
297 /* trap NULL parameters on entry */
298 if (( lpFile
== NULL
) || ( lpDirectory
== NULL
) ||
299 ( lpResult
== NULL
))
301 /* FIXME - should throw a warning, perhaps! */
302 return 2; /* File not found. Close enough, I guess. */
305 retval
= SHELL_FindExecutable( lpFile
, lpDirectory
, "open",
308 dprintf_exec(stddeb
, "FindExecutable: returning %s\n", lpResult
);
312 static char AppName
[128], AppMisc
[1536];
314 /*************************************************************************
315 * AboutDlgProc [SHELL.33]
317 LRESULT
AboutDlgProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
319 char Template
[512], AppTitle
[512];
324 SendDlgItemMessage32A(hWnd
,stc1
,STM_SETICON
,lParam
,0);
326 SendDlgItemMessage16(hWnd
,stc1
,STM_SETICON
,LOWORD(lParam
),0);
328 GetWindowText32A(hWnd
, Template
, sizeof(Template
));
329 sprintf(AppTitle
, Template
, AppName
);
330 SetWindowText32A(hWnd
, AppTitle
);
331 SetWindowText32A(GetDlgItem(hWnd
,100), AppMisc
);
337 EndDialog(hWnd
, TRUE
);
345 /*************************************************************************
346 * ShellAbout [SHELL.22]
348 INT
ShellAbout(HWND hWnd
, LPCSTR szApp
, LPCSTR szOtherStuff
, HICON hIcon
)
353 if (szApp
) strncpy(AppName
, szApp
, sizeof(AppName
));
355 AppName
[sizeof(AppName
)-1]=0;
357 if (szOtherStuff
) strncpy(AppMisc
, szOtherStuff
, sizeof(AppMisc
));
359 AppMisc
[sizeof(AppMisc
)-1]=0;
361 if (!hIcon
) hIcon
= LoadIcon(0,MAKEINTRESOURCE(OIC_WINEICON
));
362 handle
= SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX
);
363 if (!handle
) return FALSE
;
364 bRet
= DialogBoxIndirectParam( WIN_GetWindowInstance( hWnd
),
366 MODULE_GetWndProcEntry16("AboutDlgProc"),
368 SYSRES_FreeResource( handle
);
372 /*************************************************************************
373 * SHELL_GetResourceTable
375 * FIXME: Implement GetPEResourceTable in w32sys.c and call it here.
377 BYTE
* SHELL_GetResourceTable(HFILE hFile
)
379 struct mz_header_s mz_header
;
380 struct ne_header_s ne_header
;
383 _llseek( hFile
, 0, SEEK_SET
);
384 if ((FILE_Read(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
385 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (BYTE
*)-1;
387 _llseek( hFile
, mz_header
.ne_offset
, SEEK_SET
);
388 if (FILE_Read( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
391 if (ne_header
.ne_magic
== PE_SIGNATURE
)
392 { fprintf(stdnimp
,"Win32 FIXME: file %s line %i\n", __FILE__
, __LINE__
);
395 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return NULL
;
397 size
= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
399 if( size
> sizeof(NE_TYPEINFO
) )
401 BYTE
* pTypeInfo
= (BYTE
*)xmalloc(size
);
403 if( !pTypeInfo
) return NULL
;
405 _llseek(hFile
, mz_header
.ne_offset
+ne_header
.resource_tab_offset
, SEEK_SET
);
406 if( FILE_Read( hFile
, (char*)pTypeInfo
, size
) != size
)
407 { free(pTypeInfo
); return NULL
; }
415 /*************************************************************************
418 HANDLE
SHELL_LoadResource(HINSTANCE hInst
, HFILE hFile
, NE_NAMEINFO
* pNInfo
, WORD sizeShift
)
421 HANDLE handle
= DirectResAlloc( hInst
, 0x10, (DWORD
)pNInfo
->length
<< sizeShift
);
423 if( (ptr
= (BYTE
*)GlobalLock16( handle
)) )
425 _llseek( hFile
, (DWORD
)pNInfo
->offset
<< sizeShift
, SEEK_SET
);
426 FILE_Read( hFile
, (char*)ptr
, pNInfo
->length
<< sizeShift
);
432 /*************************************************************************
433 * InternalExtractIcon [SHELL.39]
435 * This abortion is called directly by Progman
437 HICON
InternalExtractIcon(HINSTANCE hInstance
, LPCSTR lpszExeFileName
, UINT nIconIndex
, WORD n
)
440 HICON
* RetPtr
= NULL
;
443 HFILE hFile
= OpenFile( lpszExeFileName
, &ofs
, OF_READ
);
445 dprintf_reg(stddeb
, "InternalExtractIcon(%04x, file '%s', start from %d, extract %d\n",
446 hInstance
, lpszExeFileName
, nIconIndex
, n
);
448 if( hFile
== HFILE_ERROR
|| !n
) return 0;
450 hRet
= GlobalAlloc16( GMEM_FIXED
, sizeof(HICON
)*n
);
451 RetPtr
= (HICON
*)GlobalLock16(hRet
);
453 *RetPtr
= (n
== 0xFFFF)? 0: 1; /* error return values */
455 pData
= SHELL_GetResourceTable(hFile
);
457 if( pData
== (BYTE
*)-1 )
459 /* FIXME: possible .ICO file */
461 fprintf(stddeb
,"InternalExtractIcon: cannot handle file %s\n", lpszExeFileName
);
463 else /* got resource table */
465 UINT iconDirCount
= 0;
467 NE_TYPEINFO
* pTInfo
= (NE_TYPEINFO
*)(pData
+ 2);
468 NE_NAMEINFO
* pIconStorage
= NULL
;
469 NE_NAMEINFO
* pIconDir
= NULL
;
471 /* find icon directory and icon repository */
473 while( pTInfo
->type_id
&& !(pIconStorage
&& pIconDir
) )
475 if( pTInfo
->type_id
== NE_RSCTYPE_GROUP_ICON
)
477 iconDirCount
= pTInfo
->count
;
478 pIconDir
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
479 dprintf_reg(stddeb
,"\tfound directory - %i icon families\n", iconDirCount
);
481 if( pTInfo
->type_id
== NE_RSCTYPE_ICON
)
483 iconCount
= pTInfo
->count
;
484 pIconStorage
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
485 dprintf_reg(stddeb
,"\ttotal icons - %i\n", iconCount
);
487 pTInfo
= (NE_TYPEINFO
*)((char*)(pTInfo
+1)+pTInfo
->count
*sizeof(NE_NAMEINFO
));
490 /* load resources and create icons */
492 if( pIconStorage
&& pIconDir
)
494 if( nIconIndex
== (UINT
)-1 ) RetPtr
[0] = iconDirCount
;
495 else if( nIconIndex
< iconDirCount
)
500 if( n
> iconDirCount
- nIconIndex
) n
= iconDirCount
- nIconIndex
;
502 for( i
= nIconIndex
; i
< nIconIndex
+ n
; i
++ )
504 hIcon
= SHELL_LoadResource( hInstance
, hFile
, pIconDir
+ (i
- nIconIndex
),
506 RetPtr
[i
-nIconIndex
] = GetIconID( hIcon
, 3 );
510 for( icon
= nIconIndex
; icon
< nIconIndex
+ n
; icon
++ )
513 for( i
= 0; i
< iconCount
; i
++ )
514 if( pIconStorage
[i
].id
== (RetPtr
[icon
-nIconIndex
] | 0x8000) )
515 hIcon
= SHELL_LoadResource( hInstance
, hFile
, pIconStorage
+ i
,
517 RetPtr
[icon
-nIconIndex
] = (hIcon
)?CURSORICON_LoadHandler( hIcon
, hInstance
, FALSE
):0;
525 /* return array with icon handles */
530 /*************************************************************************
531 * ExtractIcon [SHELL.34]
533 HICON
ExtractIcon(HINSTANCE hInstance
, LPCSTR lpszExeFileName
, WORD nIconIndex
)
535 HANDLE handle
= InternalExtractIcon(hInstance
,lpszExeFileName
,nIconIndex
, 1);
539 HICON
* ptr
= (HICON
*)GlobalLock16(handle
);
542 GlobalFree16(handle
);
548 /*************************************************************************
549 * ExtractAssociatedIcon [SHELL.36]
551 HICON
ExtractAssociatedIcon(HINSTANCE hInst
,LPSTR lpIconPath
, LPWORD lpiIcon
)
553 HICON hIcon
= ExtractIcon(hInst
, lpIconPath
, *lpiIcon
);
555 /* MAKEINTRESOURCE(2) seems to be "default" icon according to Progman
557 * For data files it probably should call FindExecutable and load
558 * icon from there. As of now FindExecutable is empty stub.
561 if( hIcon
< 2 ) hIcon
= LoadIcon( hInst
, MAKEINTRESOURCE(2));
566 /*************************************************************************
567 * FindEnvironmentString [SHELL.38]
569 * Returns a pointer into the DOS environment... Ugh.
571 LPSTR
SHELL_FindString(LPSTR lpEnv
, LPCSTR entry
)
573 UINT l
= strlen(entry
);
574 for( ; *lpEnv
; lpEnv
+=strlen(lpEnv
)+1 )
576 if( lstrncmpi(lpEnv
, entry
, l
) ) continue;
579 return (lpEnv
+ l
); /* empty entry */
580 else if ( *(lpEnv
+l
)== '=' )
581 return (lpEnv
+ l
+ 1);
586 SEGPTR
FindEnvironmentString(LPSTR str
)
588 SEGPTR spEnv
= GetDOSEnvironment();
589 LPSTR lpEnv
= (LPSTR
)PTR_SEG_TO_LIN(spEnv
);
591 LPSTR lpString
= (spEnv
)?SHELL_FindString(lpEnv
, str
):NULL
;
593 if( lpString
) /* offset should be small enough */
594 return spEnv
+ (lpString
- lpEnv
);
599 /*************************************************************************
600 * DoEnvironmentSubst [SHELL.37]
602 * Replace %KEYWORD% in the str with the value of variable KEYWORD
603 * from "DOS" environment.
605 DWORD
DoEnvironmentSubst(LPSTR str
,WORD length
)
607 LPSTR lpEnv
= (LPSTR
)PTR_SEG_TO_LIN(GetDOSEnvironment());
608 LPSTR lpBuffer
= (LPSTR
)xmalloc(length
);
610 LPSTR lpbstr
= lpBuffer
;
614 dprintf_reg(stddeb
,"DoEnvSubst: accept %s", str
);
616 while( *lpstr
&& lpbstr
- lpBuffer
< length
)
622 do { lpend
++; } while( *lpend
&& *lpend
!= '%' );
623 if( *lpend
== '%' && lpend
- lpstr
> 1 ) /* found key */
627 lpKey
= SHELL_FindString(lpEnv
, lpstr
+1);
628 if( lpKey
) /* found key value */
630 int l
= strlen(lpKey
);
632 if( l
> length
- (lpbstr
- lpBuffer
) - 1 )
634 fprintf(stdnimp
,"File %s, line %i: Env subst aborted - string too short\n",
639 strcpy(lpbstr
, lpKey
);
646 else break; /* back off and whine */
651 *lpbstr
++ = *lpstr
++;
655 if( lpstr
- str
== strlen(str
) )
657 strncpy(str
, lpBuffer
, length
);
663 dprintf_reg(stddeb
," return %s\n", str
);
668 /* Return str length in the LOWORD
669 * and 1 in HIWORD if subst was successful.
671 return (DWORD
)MAKELONG(strlen(str
), length
);
674 /*************************************************************************
675 * RegisterShellHook [SHELL.102]
677 int RegisterShellHook(void *ptr
)
679 dprintf_reg(stdnimp
, "RegisterShellHook : Empty Stub !!!\n");
684 /*************************************************************************
685 * ShellHookProc [SHELL.103]
687 int ShellHookProc(void)
689 dprintf_reg(stdnimp
, "ShellHookProc : Empty Stub !!!\n");