Release 960218
[wine] / misc / shell.c
1 /*
2  *                              Shell Library Functions
3  */
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <ctype.h>
9 #include "windows.h"
10 #include "shell.h"
11 #include "neexe.h"
12 #include "selectors.h"
13 #include "alias.h"
14 #include "relay32.h"
15 #include "resource.h"
16 #include "dlgs.h"
17 #include "win.h"
18 #include "stddebug.h"
19 #include "debug.h"
20 #include "xmalloc.h"
21
22 LPKEYSTRUCT     lphRootKey = NULL,lphTopKey = NULL;
23
24 static char RootKeyName[]=".classes", TopKeyName[] = "[top-null]";
25
26 /*************************************************************************
27  *                        SHELL_Init()
28  */
29 BOOL SHELL_Init()
30 {
31     HKEY hNewKey;
32     
33     hNewKey = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
34     lphRootKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
35     if (lphRootKey == NULL) {
36         printf("SHELL_RegCheckForRoot: Couldn't allocate root key!\n");
37         return FALSE;
38     }
39     lphRootKey->hKey = (HKEY)1;
40     lphRootKey->lpSubKey = RootKeyName;
41     lphRootKey->dwType = 0;
42     lphRootKey->lpValue = NULL;
43     lphRootKey->lpSubLvl = lphRootKey->lpNextKey = lphRootKey->lpPrevKey = NULL;
44     
45     hNewKey = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
46     lphTopKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
47     if (lphTopKey == NULL) {
48         printf("SHELL_RegCheckForRoot: Couldn't allocate top key!\n");
49         return FALSE;
50     }
51     lphTopKey->hKey = 0;
52     lphTopKey->lpSubKey = TopKeyName;
53     lphTopKey->dwType = 0;
54     lphTopKey->lpValue = NULL;
55     lphTopKey->lpSubLvl = lphRootKey;
56     lphTopKey->lpNextKey = lphTopKey->lpPrevKey = NULL;
57
58     dprintf_reg(stddeb,"SHELL_RegCheckForRoot: Root/Top created\n");
59
60     return TRUE;
61 }
62
63 /* FIXME: the loading and saving of the registry database is rather messy.
64  * bad input (while reading) may crash wine.
65  */
66 void
67 _DumpLevel(FILE *f,LPKEYSTRUCT lpTKey,int tabs)
68 {
69         LPKEYSTRUCT     lpKey;
70
71         lpKey=lpTKey->lpSubLvl;
72         while (lpKey) {
73                 int     i;
74                 for (i=0;i<tabs;i++) fprintf(f,"\t");
75                 /* implement different dwTypes ... */
76                 if (lpKey->lpValue)
77                         fprintf(f,"%s=%s\n",lpKey->lpSubKey,lpKey->lpValue);
78                 else
79                         fprintf(f,"%s\n",lpKey->lpSubKey);
80
81                 if (lpKey->lpSubLvl)
82                         _DumpLevel(f,lpKey,tabs+1);
83                 lpKey=lpKey->lpNextKey;
84         }
85 }
86
87 static void
88 _SaveKey(HKEY hKey,char *where)
89 {
90         FILE            *f;
91         LPKEYSTRUCT     lpKey;
92
93         f=fopen(where,"w");
94         if (f==NULL) {
95                 perror("registry-fopen");
96                 return;
97         }
98         switch ((DWORD)hKey) {
99         case HKEY_CLASSES_ROOT:
100                 lpKey=lphRootKey;
101                 break;
102         default:return;
103         }
104         _DumpLevel(f,lpKey,0);
105         fclose(f);
106 }
107
108 void
109 SHELL_SaveRegistry(void)
110 {
111         /* FIXME: 
112          * -implement win95 additional keytypes here
113          * (HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER or whatever)
114          * -choose better filename(s)
115          */
116         _SaveKey((HKEY)HKEY_CLASSES_ROOT,"/tmp/winereg");
117 }
118
119 #define BUFSIZE 256
120 void
121 _LoadLevel(FILE *f,LPKEYSTRUCT lpKey,int tabsexp,char *buf)
122 {
123         int             i;
124         char            *s,*t;
125         HKEY            hNewKey;
126         LPKEYSTRUCT     lpNewKey;
127
128         while (1) {
129                 if (NULL==fgets(buf,BUFSIZE,f)) {
130                         buf[0]=0;
131                         return;
132                 }
133                 for (i=0;buf[i]=='\t';i++) /*empty*/;
134                 s=buf+i;
135                 if (NULL!=(t=strchr(s,'\n'))) *t='\0';
136                 if (NULL!=(t=strchr(s,'\r'))) *t='\0';
137
138                 if (i<tabsexp) return;
139
140                 if (i>tabsexp) {
141                         hNewKey=GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
142                         lpNewKey=lpKey->lpSubLvl=(LPKEYSTRUCT)GlobalLock(hNewKey);
143                         lpNewKey->hKey          = hNewKey;
144                         lpNewKey->dwType        = 0;
145                         lpNewKey->lpSubKey      = NULL;
146                         lpNewKey->lpValue       = NULL;
147                         lpNewKey->lpSubLvl      = NULL;
148                         lpNewKey->lpNextKey     = NULL;
149                         lpNewKey->lpPrevKey     = NULL;
150                         if (NULL!=(t=strchr(s,'='))) {
151                                 *t='\0';t++;
152                                 lpNewKey->dwType        = REG_SZ;
153                                 lpNewKey->lpSubKey      = xstrdup(s);
154                                 lpNewKey->lpValue       = xstrdup(t);
155                         } else {
156                                 lpNewKey->dwType        = REG_SZ;
157                                 lpNewKey->lpSubKey      = xstrdup(s);
158                         }
159                         _LoadLevel(f,lpNewKey,tabsexp+1,buf);
160                 }
161                 for (i=0;buf[i]=='\t';i++) /*empty*/;
162                 s=buf+i;
163                 if (i<tabsexp) return;
164                 if (buf[0]=='\0') break; /* marks end of file */
165                 /* we have a buf now. even when returning from _LoadLevel */
166                 hNewKey         = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
167                 lpNewKey        = lpKey->lpNextKey=(LPKEYSTRUCT)GlobalLock(hNewKey);
168                 lpNewKey->lpPrevKey     = lpKey;
169                 lpNewKey->hKey          = hNewKey;
170                 lpNewKey->dwType        = 0;
171                 lpNewKey->lpSubKey      = NULL;
172                 lpNewKey->lpValue       = NULL;
173                 lpNewKey->lpSubLvl      = NULL;
174                 lpNewKey->lpNextKey     = NULL;
175                 if (NULL!=(t=strchr(s,'='))) {
176                         *t='\0';t++;
177                         lpNewKey->dwType        = REG_SZ;
178                         lpNewKey->lpSubKey      = xstrdup(s);
179                         lpNewKey->lpValue       = xstrdup(t);
180                 } else {
181                         lpNewKey->dwType        = REG_SZ;
182                         lpNewKey->lpSubKey      = xstrdup(s);
183                 }
184                 lpKey=lpNewKey;
185         }
186 }
187
188 void
189 _LoadKey(HKEY hKey,char *from) 
190 {
191         FILE            *f;
192         LPKEYSTRUCT     lpKey;
193         char            buf[BUFSIZE]; /* FIXME: long enough? */
194
195         f=fopen(from,"r");
196         if (f==NULL) {
197                 perror("fopen-registry-read");
198                 return;
199         }
200         switch ((DWORD)hKey) {
201         case HKEY_CLASSES_ROOT:
202                 lpKey=lphRootKey;
203                 break;
204         default:return;
205         }
206         _LoadLevel(f,lpKey,-1,buf);
207 }
208
209 void
210 SHELL_LoadRegistry(void) 
211 {
212         _LoadKey((HKEY)HKEY_CLASSES_ROOT,"/tmp/winereg");
213 }
214
215 /*************************************************************************
216  *                              RegOpenKey              [SHELL.1]
217  */
218 LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, LPHKEY lphKey)
219 {
220         LPKEYSTRUCT     lpKey,lpNextKey;
221         LPCSTR          ptr;
222         char            str[128];
223
224         dprintf_reg(stddeb, "RegOpenKey(%08lX, %p='%s', %p)\n",
225                                        (DWORD)hKey, lpSubKey, lpSubKey, lphKey);
226         if (lphKey == NULL) return SHELL_ERROR_INVALID_PARAMETER;
227         switch((DWORD)hKey) {
228         case 0: 
229           lpKey = lphTopKey; break;
230         case HKEY_CLASSES_ROOT: /* == 1 */
231         case 0x80000000:
232           lpKey = lphRootKey; break;
233         default: 
234           dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", (DWORD)hKey);
235           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
236         }
237         if (lpSubKey == NULL || !*lpSubKey)  { 
238           *lphKey = hKey; 
239           return SHELL_ERROR_SUCCESS; 
240         }
241         while(*lpSubKey) {
242           ptr = strchr(lpSubKey,'\\');
243           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
244           strncpy(str,lpSubKey,ptr-lpSubKey);
245           str[ptr-lpSubKey] = 0;
246           lpSubKey = ptr; 
247           if (*lpSubKey) lpSubKey++;
248           
249           lpNextKey = lpKey->lpSubLvl;
250           while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
251                 lpKey = lpNextKey;
252                 if (lpKey) lpNextKey = lpKey->lpNextKey;
253           }
254           if (lpKey == NULL) {
255             dprintf_reg(stddeb,"RegOpenKey: key %s not found!\n",str);
256             return SHELL_ERROR_BADKEY;
257           }         
258         }
259         *lphKey = lpKey->hKey;
260         return SHELL_ERROR_SUCCESS;
261 }
262
263
264 /*************************************************************************
265  *                              RegCreateKey            [SHELL.2]
266  */
267 LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, LPHKEY lphKey)
268 {
269         HKEY            hNewKey;
270         LPKEYSTRUCT     lpNewKey;
271         LPKEYSTRUCT     lpKey;
272         LPKEYSTRUCT     lpPrevKey;
273         LPCSTR          ptr;
274         char            str[128];
275
276         dprintf_reg(stddeb, "RegCreateKey(%08lX, '%s', %p)\n",  (DWORD)hKey, lpSubKey, lphKey);
277         if (lphKey == NULL) return SHELL_ERROR_INVALID_PARAMETER;
278         switch((DWORD)hKey) {
279         case 0: 
280           lpKey = lphTopKey; break;
281         case HKEY_CLASSES_ROOT: /* == 1 */
282         case 0x80000000:
283         case 0x80000001:
284           lpKey = lphRootKey; break;
285         default: 
286           dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", (DWORD)hKey);
287           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
288         }
289         if (lpSubKey == NULL || !*lpSubKey)  { 
290           *lphKey = hKey; 
291           return SHELL_ERROR_SUCCESS;
292         }
293         while (*lpSubKey) {
294           dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
295           ptr = strchr(lpSubKey,'\\');
296           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
297           strncpy(str,lpSubKey,ptr-lpSubKey);
298           str[ptr-lpSubKey] = 0;
299           lpSubKey = ptr; 
300           if (*lpSubKey) lpSubKey++;
301           
302           lpPrevKey = lpKey;
303           lpKey = lpKey->lpSubLvl;
304           while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
305             lpKey = lpKey->lpNextKey; 
306           }
307           if (lpKey == NULL) {
308             hNewKey = GlobalAlloc(GMEM_MOVEABLE, sizeof(KEYSTRUCT));
309             lpNewKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
310             if (lpNewKey == NULL) {
311               printf("RegCreateKey // Can't alloc new key !\n");
312               return SHELL_ERROR_OUTOFMEMORY;
313             }
314             lpNewKey->hKey = hNewKey;
315             lpNewKey->lpSubKey = malloc(strlen(str) + 1);
316             if (lpNewKey->lpSubKey == NULL) {
317               printf("RegCreateKey // Can't alloc key string !\n");
318               return SHELL_ERROR_OUTOFMEMORY;
319             }
320             strcpy(lpNewKey->lpSubKey, str);
321             lpNewKey->lpNextKey = lpPrevKey->lpSubLvl;
322             lpNewKey->lpPrevKey = NULL;
323             lpPrevKey->lpSubLvl = lpNewKey;
324
325             lpNewKey->dwType = 0;
326             lpNewKey->lpValue = NULL;
327             lpNewKey->lpSubLvl = NULL;
328             *lphKey = hNewKey;
329             dprintf_reg(stddeb,"RegCreateKey // successful '%s' key=%08lX !\n", str, (DWORD)hNewKey);
330             lpKey = lpNewKey;
331           } else {
332             *lphKey = lpKey->hKey;
333             dprintf_reg(stddeb,"RegCreateKey // found '%s', key=%08lX\n", str, (DWORD)*lphKey);
334           }
335         }
336         return SHELL_ERROR_SUCCESS;
337 }
338
339
340 /*************************************************************************
341  *                              RegCloseKey             [SHELL.3]
342  */
343 LONG RegCloseKey(HKEY hKey)
344 {
345         dprintf_reg(stdnimp, "EMPTY STUB !!! RegCloseKey(%08lX);\n", (DWORD)hKey);
346         return SHELL_ERROR_SUCCESS;
347 }
348
349
350 /*************************************************************************
351  *                              RegDeleteKey            [SHELL.4]
352  */
353 LONG RegDeleteKey(HKEY hKey, LPCSTR lpSubKey)
354 {
355         dprintf_reg(stdnimp, "EMPTY STUB !!! RegDeleteKey(%08lX, '%s');\n",
356                      (DWORD)hKey, lpSubKey);
357         return SHELL_ERROR_SUCCESS;
358 }
359
360
361 /*************************************************************************
362  *                              RegSetValue             [SHELL.5]
363  */
364 LONG RegSetValue(HKEY hKey, LPCSTR lpSubKey, DWORD dwType, 
365                  LPCSTR lpVal, DWORD dwIgnored)
366 {
367     HKEY        hRetKey;
368     LPKEYSTRUCT lpKey;
369     LONG        dwRet;
370     dprintf_reg(stddeb, "RegSetValue(%08lX, '%s', %08lX, '%s', %08lX);\n",
371                 (DWORD)hKey, lpSubKey, dwType, lpVal, dwIgnored);
372     /*if (lpSubKey == NULL) return SHELL_ERROR_INVALID_PARAMETER;*/
373     if (lpVal == NULL) return SHELL_ERROR_INVALID_PARAMETER;
374     if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != SHELL_ERROR_SUCCESS) {
375         dprintf_reg(stddeb, "RegSetValue // key not found ... so create it !\n");
376         if ((dwRet = RegCreateKey(hKey, lpSubKey, &hRetKey)) != SHELL_ERROR_SUCCESS) {
377             fprintf(stderr, "RegSetValue // key creation error %08lX !\n", dwRet);
378             return dwRet;
379         }
380     }
381     lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
382     if (lpKey == NULL) return SHELL_ERROR_BADKEY;
383     if (lpKey->lpValue != NULL) free(lpKey->lpValue);
384     lpKey->lpValue = xmalloc(strlen(lpVal) + 1);
385     strcpy(lpKey->lpValue, lpVal);
386     dprintf_reg(stddeb,"RegSetValue // successful key='%s' val='%s' !\n", lpSubKey, lpKey->lpValue);
387     return SHELL_ERROR_SUCCESS;
388 }
389
390
391 /*************************************************************************
392  *                              RegQueryValue           [SHELL.6]
393  */
394 LONG RegQueryValue(HKEY hKey, LPCSTR lpSubKey, LPSTR lpVal, LPLONG lpcb)
395 {
396         HKEY            hRetKey;
397         LPKEYSTRUCT     lpKey;
398         LONG            dwRet;
399         int                     size;
400         dprintf_reg(stddeb, "RegQueryValue(%08lX, '%s', %p, %p);\n",
401                     (DWORD)hKey, lpSubKey, lpVal, lpcb);
402         /*if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;*/
403         if (lpVal == NULL) return SHELL_ERROR_INVALID_PARAMETER;
404         if (lpcb == NULL) return SHELL_ERROR_INVALID_PARAMETER;
405         if (!*lpcb) return SHELL_ERROR_INVALID_PARAMETER;
406
407         if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != SHELL_ERROR_SUCCESS) {
408                 fprintf(stderr, "RegQueryValue // key not found !\n");
409                 return dwRet;
410         }
411         lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
412         if (lpKey == NULL) return SHELL_ERROR_BADKEY;
413         if (lpKey->lpValue != NULL) {
414           if ((size = strlen(lpKey->lpValue)+1) > *lpcb){
415             strncpy(lpVal,lpKey->lpValue,*lpcb-1);
416             lpVal[*lpcb-1] = 0;
417           } else {
418             strcpy(lpVal,lpKey->lpValue);
419             *lpcb = size;
420           }
421         } else {
422           *lpVal = 0;
423           *lpcb = (LONG)1;
424         }
425         dprintf_reg(stddeb,"RegQueryValue // return '%s' !\n", lpVal);
426         return SHELL_ERROR_SUCCESS;
427 }
428
429
430 /*************************************************************************
431  *                              RegEnumKey              [SHELL.7]
432  */
433 LONG RegEnumKey(HKEY hKey, DWORD dwSubKey, LPSTR lpBuf, DWORD dwSize)
434 {
435         LPKEYSTRUCT     lpKey;
436         LONG            len;
437
438         dprintf_reg(stddeb, "RegEnumKey(%08lX, %ld)\n", (DWORD)hKey, dwSubKey);
439         if (lpBuf == NULL) return SHELL_ERROR_INVALID_PARAMETER;
440         switch((DWORD)hKey) {
441         case 0: 
442           lpKey = lphTopKey; break;
443         case HKEY_CLASSES_ROOT: /* == 1 */
444         case 0x80000000:
445           lpKey = lphRootKey; break;
446         default: 
447           dprintf_reg(stddeb,"RegEnumKey // specific key = %08lX !\n", (DWORD)hKey);
448           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
449         }
450         lpKey = lpKey->lpSubLvl;
451         while(lpKey != NULL){
452           if (!dwSubKey){
453             len = MIN(dwSize-1,strlen(lpKey->lpSubKey));
454             strncpy(lpBuf,lpKey->lpSubKey,len);
455             lpBuf[len] = 0;
456             dprintf_reg(stddeb, "RegEnumKey: found %s\n",lpBuf);
457             return SHELL_ERROR_SUCCESS;
458           }
459           dwSubKey--;
460           lpKey = lpKey->lpNextKey;
461         }
462         dprintf_reg(stddeb, "RegEnumKey: key not found!\n");
463         return SHELL_ERROR_INVALID_PARAMETER;
464 }
465
466
467 /*************************************************************************
468  *                              DragAcceptFiles         [SHELL.9]
469  */
470 void DragAcceptFiles(HWND hWnd, BOOL b)
471 {
472     /* flips WS_EX_ACCEPTFILES bit according to the value of b */
473     dprintf_reg(stddeb,"DragAcceptFiles("NPFMT", %u) old exStyle %08lx\n",
474                 hWnd,b,GetWindowLong(hWnd,GWL_EXSTYLE));
475
476     SetWindowLong(hWnd,GWL_EXSTYLE,
477                   GetWindowLong(hWnd,GWL_EXSTYLE) | b*(LONG)WS_EX_ACCEPTFILES);
478 }
479
480
481 /*************************************************************************
482  *                              DragQueryFile           [SHELL.11]
483  */
484 UINT DragQueryFile(HDROP hDrop, WORD wFile, LPSTR lpszFile, WORD wLength)
485 {
486     /* hDrop is a global memory block allocated with GMEM_SHARE 
487      * with DROPFILESTRUCT as a header and filenames following
488      * it, zero length filename is in the end */       
489     
490     LPDROPFILESTRUCT lpDropFileStruct;
491     LPSTR lpCurrent;
492     WORD  i;
493     
494     dprintf_reg(stddeb,"DragQueryFile("NPFMT", %i, %p, %u)\n",
495                 hDrop,wFile,lpszFile,wLength);
496     
497     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop); 
498     if(!lpDropFileStruct)
499     {
500         dprintf_reg(stddeb,"DragQueryFile: unable to lock handle!\n");
501         return 0;
502     } 
503     lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
504     
505     i = 0;
506     while (i++ < wFile)
507     {
508         while (*lpCurrent++);  /* skip filename */
509         if (!*lpCurrent) 
510             return (wFile == 0xFFFF) ? i : 0;  
511     }
512     
513     i = strlen(lpCurrent); 
514     if (!lpszFile) return i+1;   /* needed buffer size */
515     
516     i = (wLength > i) ? i : wLength-1;
517     strncpy(lpszFile, lpCurrent, i);
518     lpszFile[i] = '\0';
519     
520     GlobalUnlock(hDrop);
521     return i;
522 }
523
524
525 /*************************************************************************
526  *                              DragFinish              [SHELL.12]
527  */
528 void DragFinish(HDROP h)
529 {
530     GlobalFree((HGLOBAL)h);
531 }
532
533
534 /*************************************************************************
535  *                              DragQueryPoint          [SHELL.13]
536  */
537 BOOL DragQueryPoint(HDROP hDrop, POINT FAR *p)
538 {
539     LPDROPFILESTRUCT lpDropFileStruct;  
540     BOOL             bRet;
541
542     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
543
544     memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT));
545     bRet = lpDropFileStruct->fInNonClientArea;
546
547     GlobalUnlock(hDrop);
548     return bRet;
549 }
550
551
552 /*************************************************************************
553  *                              ShellExecute            [SHELL.20]
554  */
555 HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
556 {
557     char cmd[400];
558     char *p,*x;
559     long len;
560     char subclass[200];
561     /* OK. We are supposed to lookup the program associated with lpFile,
562      * then to execute it using that program. If lpFile is a program,
563      * we have to pass the parameters. If an instance is already running,
564      * we might have to send DDE commands.
565      */
566     dprintf_exec(stddeb, "ShellExecute("NPFMT",'%s','%s','%s','%s',%x)\n",
567                 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
568                 lpParameters ? lpParameters : "<null>", 
569                 lpDirectory ? lpDirectory : "<null>", iShowCmd);
570     if (lpFile==NULL) return 0; /* should not happen */
571     if (lpOperation==NULL) /* default is open */
572       lpOperation="open";
573     p=strrchr(lpFile,'.');
574     if (p!=NULL) {
575       x=p; /* the suffixes in the register database are lowercased */
576       while (*x) {*x=tolower(*x);x++;}
577     }
578     if (p==NULL || !strcmp(p,".exe")) {
579       p=".exe";
580       if (lpParameters) {
581         sprintf(cmd,"%s %s",lpFile,lpParameters);
582       } else {
583         strcpy(cmd,lpFile);
584       }
585     } else {
586       len=200;
587       if (RegQueryValue((HKEY)HKEY_CLASSES_ROOT,p,subclass,&len)==SHELL_ERROR_SUCCESS) {
588         if (len>20)
589           fprintf(stddeb,"ShellExecute:subclass with len %ld? (%s), please report.\n",len,subclass);
590         subclass[len]='\0';
591         strcat(subclass,"\\shell\\");
592         strcat(subclass,lpOperation);
593         strcat(subclass,"\\command");
594         dprintf_exec(stddeb,"ShellExecute:looking for %s.\n",subclass);
595         len=400;
596         if (RegQueryValue((HKEY)HKEY_CLASSES_ROOT,subclass,cmd,&len)==SHELL_ERROR_SUCCESS) {
597           char *t;
598           dprintf_exec(stddeb,"ShellExecute:...got %s\n",cmd);
599           cmd[len]='\0';
600           t=strstr(cmd,"%1");
601           if (t==NULL) {
602             strcat(cmd," ");
603             strcat(cmd,lpFile);
604           } else {
605             char *s;
606             s=xmalloc(len+strlen(lpFile)+10);
607             strncpy(s,cmd,t-cmd);
608             s[t-cmd]='\0';
609             strcat(s,lpFile);
610             strcat(s,t+2);
611             strcpy(cmd,s);
612             free(s);
613           }
614           /* does this use %x magic too? */
615           if (lpParameters) {
616             strcat(cmd," ");
617             strcat(cmd,lpParameters);
618           }
619         } else {
620           fprintf(stddeb,"ShellExecute: No %s\\shell\\%s\\command found for \"%s\" suffix.\n",subclass,lpOperation,p);
621           return (HINSTANCE)14; /* unknown type */
622         }
623       } else {
624         fprintf(stddeb,"ShellExecute: No operation found for \"%s\" suffix.\n",p);
625         return (HINSTANCE)14; /* file not found */
626       }
627     }
628     dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
629     return WinExec(cmd,iShowCmd);
630 }
631
632
633 /*************************************************************************
634  *                              FindExecutable          [SHELL.21]
635  */
636 HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
637 {
638         fprintf(stdnimp, "FindExecutable : Empty Stub !!!\n");
639         return 0;
640 }
641
642 static char AppName[128], AppMisc[906];
643
644 /*************************************************************************
645  *                              AboutDlgProc            [SHELL.33]
646  */
647 LRESULT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
648 {
649   char Template[512], AppTitle[512];
650  
651   switch(msg) {
652    case WM_INITDIALOG:
653 #ifdef WINELIB32
654     SendDlgItemMessage(hWnd,stc1,STM_SETICON,lParam,0);
655 #else
656     SendDlgItemMessage(hWnd,stc1,STM_SETICON,LOWORD(lParam),0);
657 #endif
658     GetWindowText(hWnd, Template, 511);
659     sprintf(AppTitle, Template, AppName);
660     SetWindowText(hWnd, AppTitle);
661     SetWindowText(GetDlgItem(hWnd,100), AppMisc);
662     return 1;
663     
664    case WM_COMMAND:
665     switch (wParam) {
666      case IDOK:
667       EndDialog(hWnd, TRUE);
668       return TRUE;
669     }
670     break;
671   }
672   return FALSE;
673 }
674
675 /*************************************************************************
676  *                              ShellAbout              [SHELL.22]
677  */
678 INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon)
679 {
680     HANDLE handle;
681     BOOL bRet;
682     DWORD WineProc,Win16Proc,Win32Proc;
683     static int initialized=0;
684
685     if (szApp) strncpy(AppName, szApp, sizeof(AppName));
686     else *AppName = 0;
687     AppName[sizeof(AppName)-1]=0;
688
689     if (szOtherStuff) strncpy(AppMisc, szOtherStuff, sizeof(AppMisc));
690     else *AppMisc = 0;
691     AppMisc[sizeof(AppMisc)-1]=0;
692
693     if (!hIcon) hIcon = LoadIcon(0,MAKEINTRESOURCE(OIC_WINEICON));
694     
695     if(!initialized)
696     {
697         WineProc=(DWORD)AboutDlgProc;
698         Win16Proc=(DWORD)GetWndProcEntry16("AboutDlgProc");
699         Win32Proc=(DWORD)RELAY32_GetEntryPoint(RELAY32_GetBuiltinDLL("WINPROCS32"),
700                                                "AboutDlgProc",0);
701         ALIAS_RegisterAlias(WineProc,Win16Proc,Win32Proc);
702         initialized=1;
703     }
704
705     handle = SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX );
706     if (!handle) return FALSE;
707     bRet = DialogBoxIndirectParam( WIN_GetWindowInstance( hWnd ),
708                                    handle, hWnd,
709                                    GetWndProcEntry16("AboutDlgProc"), 
710                                    (LONG)hIcon );
711     SYSRES_FreeResource( handle );
712     return bRet;
713 }
714
715 /*************************************************************************
716  *                              ExtractIcon             [SHELL.34]
717  */
718 HICON ExtractIcon(HINSTANCE hInst, LPCSTR lpszExeFileName, UINT nIconIndex)
719 {
720         HICON   hIcon = 0;
721         HINSTANCE hInst2 = hInst;
722         dprintf_reg(stddeb, "ExtractIcon("NPFMT", '%s', %d\n", 
723                         hInst, lpszExeFileName, nIconIndex);
724         return 0;
725         if (lpszExeFileName != NULL) {
726                 hInst2 = LoadModule(lpszExeFileName,(LPVOID)-1);
727         }
728         if (hInst2 != 0 && nIconIndex == (UINT)-1) {
729 #if 0
730                 count = GetRsrcCount(hInst2, NE_RSCTYPE_GROUP_ICON);
731                 dprintf_reg(stddeb, "ExtractIcon // '%s' has %d icons !\n", lpszExeFileName, count);
732                 return (HICON)count;
733 #endif
734         }
735         if (hInst2 != hInst && hInst2 != 0) {
736                 FreeLibrary(hInst2);
737         }
738         return hIcon;
739 }
740
741
742 /*************************************************************************
743  *                              ExtractAssociatedIcon   [SHELL.36]
744  */
745 HICON ExtractAssociatedIcon(HINSTANCE hInst,LPSTR lpIconPath, LPWORD lpiIcon)
746 {
747     dprintf_reg(stdnimp, "ExtractAssociatedIcon : Empty Stub !!!\n");
748     return 0;
749 }
750
751 /*************************************************************************
752  *              DoEnvironmentSubst      [SHELL.37]
753  */
754 DWORD DoEnvironmentSubst(LPSTR str,WORD len)
755 {
756     dprintf_reg(stdnimp, "DoEnvironmentSubst(%s,%x): Empty Stub !!!\n",str,len);
757     return 0;
758 }
759
760 /*************************************************************************
761  *                              RegisterShellHook       [SHELL.102]
762  */
763 int RegisterShellHook(void *ptr) 
764 {
765         dprintf_reg(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
766         return 0;
767 }
768
769
770 /*************************************************************************
771  *                              ShellHookProc           [SHELL.103]
772  */
773 int ShellHookProc(void) 
774 {
775         dprintf_reg(stdnimp, "ShellHookProc : Empty Stub !!!\n");
776         return 0;
777 }