Release 960324
[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             dprintf_reg(stddeb,"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         case 0x80000001:
233           lpKey = lphRootKey; break;
234         default: 
235           dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", (DWORD)hKey);
236           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
237         }
238         if (lpSubKey == NULL || !*lpSubKey)  { 
239           *lphKey = hKey; 
240           return SHELL_ERROR_SUCCESS; 
241         }
242         while(*lpSubKey) {
243           ptr = strchr(lpSubKey,'\\');
244           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
245           strncpy(str,lpSubKey,ptr-lpSubKey);
246           str[ptr-lpSubKey] = 0;
247           lpSubKey = ptr; 
248           if (*lpSubKey) lpSubKey++;
249           
250           lpNextKey = lpKey->lpSubLvl;
251           while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
252                 lpKey = lpNextKey;
253                 if (lpKey) lpNextKey = lpKey->lpNextKey;
254           }
255           if (lpKey == NULL) {
256             dprintf_reg(stddeb,"RegOpenKey: key %s not found!\n",str);
257             return SHELL_ERROR_BADKEY;
258           }         
259         }
260         *lphKey = lpKey->hKey;
261         return SHELL_ERROR_SUCCESS;
262 }
263
264
265 /*************************************************************************
266  *                              RegCreateKey            [SHELL.2]
267  */
268 LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, LPHKEY lphKey)
269 {
270         HKEY            hNewKey;
271         LPKEYSTRUCT     lpNewKey;
272         LPKEYSTRUCT     lpKey;
273         LPKEYSTRUCT     lpPrevKey;
274         LPCSTR          ptr;
275         char            str[128];
276
277         dprintf_reg(stddeb, "RegCreateKey(%08lX, '%s', %p)\n",  (DWORD)hKey, lpSubKey, lphKey);
278         if (lphKey == NULL) return SHELL_ERROR_INVALID_PARAMETER;
279         switch((DWORD)hKey) {
280         case 0: 
281           lpKey = lphTopKey; break;
282         case HKEY_CLASSES_ROOT: /* == 1 */
283         case 0x80000000:
284         case 0x80000001:
285           lpKey = lphRootKey; break;
286         default: 
287           dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", (DWORD)hKey);
288           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
289         }
290         if (lpSubKey == NULL || !*lpSubKey)  { 
291           *lphKey = hKey; 
292           return SHELL_ERROR_SUCCESS;
293         }
294         while (*lpSubKey) {
295           dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
296           ptr = strchr(lpSubKey,'\\');
297           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
298           strncpy(str,lpSubKey,ptr-lpSubKey);
299           str[ptr-lpSubKey] = 0;
300           lpSubKey = ptr; 
301           if (*lpSubKey) lpSubKey++;
302           
303           lpPrevKey = lpKey;
304           lpKey = lpKey->lpSubLvl;
305           while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
306             lpKey = lpKey->lpNextKey; 
307           }
308           if (lpKey == NULL) {
309             hNewKey = GlobalAlloc(GMEM_MOVEABLE, sizeof(KEYSTRUCT));
310             lpNewKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
311             if (lpNewKey == NULL) {
312               printf("RegCreateKey // Can't alloc new key !\n");
313               return SHELL_ERROR_OUTOFMEMORY;
314             }
315             lpNewKey->hKey = hNewKey;
316             lpNewKey->lpSubKey = malloc(strlen(str) + 1);
317             if (lpNewKey->lpSubKey == NULL) {
318               printf("RegCreateKey // Can't alloc key string !\n");
319               return SHELL_ERROR_OUTOFMEMORY;
320             }
321             strcpy(lpNewKey->lpSubKey, str);
322             lpNewKey->lpNextKey = lpPrevKey->lpSubLvl;
323             lpNewKey->lpPrevKey = NULL;
324             lpPrevKey->lpSubLvl = lpNewKey;
325
326             lpNewKey->dwType = 0;
327             lpNewKey->lpValue = NULL;
328             lpNewKey->lpSubLvl = NULL;
329             *lphKey = hNewKey;
330             dprintf_reg(stddeb,"RegCreateKey // successful '%s' key=%08lX !\n", str, (DWORD)hNewKey);
331             lpKey = lpNewKey;
332           } else {
333             *lphKey = lpKey->hKey;
334             dprintf_reg(stddeb,"RegCreateKey // found '%s', key=%08lX\n", str, (DWORD)*lphKey);
335           }
336         }
337         return SHELL_ERROR_SUCCESS;
338 }
339
340
341 /*************************************************************************
342  *                              RegCloseKey             [SHELL.3]
343  */
344 LONG RegCloseKey(HKEY hKey)
345 {
346         dprintf_reg(stdnimp, "EMPTY STUB !!! RegCloseKey(%08lX);\n", (DWORD)hKey);
347         return SHELL_ERROR_SUCCESS;
348 }
349
350
351 /*************************************************************************
352  *                              RegDeleteKey            [SHELL.4]
353  */
354 LONG RegDeleteKey(HKEY hKey, LPCSTR lpSubKey)
355 {
356         dprintf_reg(stdnimp, "EMPTY STUB !!! RegDeleteKey(%08lX, '%s');\n",
357                      (DWORD)hKey, lpSubKey);
358         return SHELL_ERROR_SUCCESS;
359 }
360
361
362 /*************************************************************************
363  *                              RegSetValue             [SHELL.5]
364  */
365 LONG RegSetValue(HKEY hKey, LPCSTR lpSubKey, DWORD dwType, 
366                  LPCSTR lpVal, DWORD dwIgnored)
367 {
368     HKEY        hRetKey;
369     LPKEYSTRUCT lpKey;
370     LONG        dwRet;
371     dprintf_reg(stddeb, "RegSetValue(%08lX, '%s', %08lX, '%s', %08lX);\n",
372                 (DWORD)hKey, lpSubKey, dwType, lpVal, dwIgnored);
373     /*if (lpSubKey == NULL) return SHELL_ERROR_INVALID_PARAMETER;*/
374     if (lpVal == NULL) return SHELL_ERROR_INVALID_PARAMETER;
375     if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != SHELL_ERROR_SUCCESS) {
376         dprintf_reg(stddeb, "RegSetValue // key not found ... so create it !\n");
377         if ((dwRet = RegCreateKey(hKey, lpSubKey, &hRetKey)) != SHELL_ERROR_SUCCESS) {
378             fprintf(stderr, "RegSetValue // key creation error %08lX !\n", dwRet);
379             return dwRet;
380         }
381     }
382     lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
383     if (lpKey == NULL) return SHELL_ERROR_BADKEY;
384     if (lpKey->lpValue != NULL) free(lpKey->lpValue);
385     lpKey->lpValue = xmalloc(strlen(lpVal) + 1);
386     strcpy(lpKey->lpValue, lpVal);
387     dprintf_reg(stddeb,"RegSetValue // successful key='%s' val='%s' !\n", lpSubKey, lpKey->lpValue);
388     return SHELL_ERROR_SUCCESS;
389 }
390
391
392 /*************************************************************************
393  *                              RegQueryValue           [SHELL.6]
394  */
395 LONG RegQueryValue(HKEY hKey, LPCSTR lpSubKey, LPSTR lpVal, LPLONG lpcb)
396 {
397         HKEY            hRetKey;
398         LPKEYSTRUCT     lpKey;
399         LONG            dwRet;
400         int                     size;
401         dprintf_reg(stddeb, "RegQueryValue(%08lX, '%s', %p, %p);\n",
402                     (DWORD)hKey, lpSubKey, lpVal, lpcb);
403         /*if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;*/
404         if (lpVal == NULL) return SHELL_ERROR_INVALID_PARAMETER;
405         if (lpcb == NULL) return SHELL_ERROR_INVALID_PARAMETER;
406         if (!*lpcb) return SHELL_ERROR_INVALID_PARAMETER;
407
408         if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != SHELL_ERROR_SUCCESS) {
409                 fprintf(stderr, "RegQueryValue // key not found !\n");
410                 return dwRet;
411         }
412         lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
413         if (lpKey == NULL) return SHELL_ERROR_BADKEY;
414         if (lpKey->lpValue != NULL) {
415           if ((size = strlen(lpKey->lpValue)+1) > *lpcb){
416             strncpy(lpVal,lpKey->lpValue,*lpcb-1);
417             lpVal[*lpcb-1] = 0;
418           } else {
419             strcpy(lpVal,lpKey->lpValue);
420             *lpcb = size;
421           }
422         } else {
423           *lpVal = 0;
424           *lpcb = (LONG)1;
425         }
426         dprintf_reg(stddeb,"RegQueryValue // return '%s' !\n", lpVal);
427         return SHELL_ERROR_SUCCESS;
428 }
429
430
431 /*************************************************************************
432  *                              RegEnumKey              [SHELL.7]
433  */
434 LONG RegEnumKey(HKEY hKey, DWORD dwSubKey, LPSTR lpBuf, DWORD dwSize)
435 {
436         LPKEYSTRUCT     lpKey;
437         LONG            len;
438
439         dprintf_reg(stddeb, "RegEnumKey(%08lX, %ld)\n", (DWORD)hKey, dwSubKey);
440         if (lpBuf == NULL) return SHELL_ERROR_INVALID_PARAMETER;
441         switch((DWORD)hKey) {
442         case 0: 
443           lpKey = lphTopKey; break;
444         case HKEY_CLASSES_ROOT: /* == 1 */
445         case 0x80000000:
446         case 0x80000001:
447           lpKey = lphRootKey; break;
448         default: 
449           dprintf_reg(stddeb,"RegEnumKey // specific key = %08lX !\n", (DWORD)hKey);
450           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
451         }
452         lpKey = lpKey->lpSubLvl;
453         while(lpKey != NULL){
454           if (!dwSubKey){
455             len = MIN(dwSize-1,strlen(lpKey->lpSubKey));
456             strncpy(lpBuf,lpKey->lpSubKey,len);
457             lpBuf[len] = 0;
458             dprintf_reg(stddeb, "RegEnumKey: found %s\n",lpBuf);
459             return SHELL_ERROR_SUCCESS;
460           }
461           dwSubKey--;
462           lpKey = lpKey->lpNextKey;
463         }
464         dprintf_reg(stddeb, "RegEnumKey: key not found!\n");
465         return SHELL_ERROR_INVALID_PARAMETER;
466 }
467
468
469 /*************************************************************************
470  *                              DragAcceptFiles         [SHELL.9]
471  */
472 void DragAcceptFiles(HWND hWnd, BOOL b)
473 {
474     /* flips WS_EX_ACCEPTFILES bit according to the value of b */
475     dprintf_reg(stddeb,"DragAcceptFiles(%04x, %u) old exStyle %08lx\n",
476                 hWnd,b,GetWindowLong(hWnd,GWL_EXSTYLE));
477
478     SetWindowLong(hWnd,GWL_EXSTYLE,
479                   GetWindowLong(hWnd,GWL_EXSTYLE) | b*(LONG)WS_EX_ACCEPTFILES);
480 }
481
482
483 /*************************************************************************
484  *                              DragQueryFile           [SHELL.11]
485  */
486 UINT DragQueryFile(HDROP hDrop, WORD wFile, LPSTR lpszFile, WORD wLength)
487 {
488     /* hDrop is a global memory block allocated with GMEM_SHARE 
489      * with DROPFILESTRUCT as a header and filenames following
490      * it, zero length filename is in the end */       
491     
492     LPDROPFILESTRUCT lpDropFileStruct;
493     LPSTR lpCurrent;
494     WORD  i;
495     
496     dprintf_reg(stddeb,"DragQueryFile(%04x, %i, %p, %u)\n",
497                 hDrop,wFile,lpszFile,wLength);
498     
499     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop); 
500     if(!lpDropFileStruct)
501     {
502         dprintf_reg(stddeb,"DragQueryFile: unable to lock handle!\n");
503         return 0;
504     } 
505     lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
506     
507     i = 0;
508     while (i++ < wFile)
509     {
510         while (*lpCurrent++);  /* skip filename */
511         if (!*lpCurrent) 
512             return (wFile == 0xFFFF) ? i : 0;  
513     }
514     
515     i = strlen(lpCurrent); 
516     if (!lpszFile) return i+1;   /* needed buffer size */
517     
518     i = (wLength > i) ? i : wLength-1;
519     strncpy(lpszFile, lpCurrent, i);
520     lpszFile[i] = '\0';
521     
522     GlobalUnlock(hDrop);
523     return i;
524 }
525
526
527 /*************************************************************************
528  *                              DragFinish              [SHELL.12]
529  */
530 void DragFinish(HDROP h)
531 {
532     GlobalFree((HGLOBAL)h);
533 }
534
535
536 /*************************************************************************
537  *                              DragQueryPoint          [SHELL.13]
538  */
539 BOOL DragQueryPoint(HDROP hDrop, POINT FAR *p)
540 {
541     LPDROPFILESTRUCT lpDropFileStruct;  
542     BOOL             bRet;
543
544     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
545
546     memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT));
547     bRet = lpDropFileStruct->fInNonClientArea;
548
549     GlobalUnlock(hDrop);
550     return bRet;
551 }
552
553
554 /*************************************************************************
555  *                              ShellExecute            [SHELL.20]
556  */
557 HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
558 {
559     char cmd[400];
560     char *p,*x;
561     long len;
562     char subclass[200];
563     /* OK. We are supposed to lookup the program associated with lpFile,
564      * then to execute it using that program. If lpFile is a program,
565      * we have to pass the parameters. If an instance is already running,
566      * we might have to send DDE commands.
567      */
568     dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
569                 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
570                 lpParameters ? lpParameters : "<null>", 
571                 lpDirectory ? lpDirectory : "<null>", iShowCmd);
572     if (lpFile==NULL) return 0; /* should not happen */
573     if (lpOperation==NULL) /* default is open */
574       lpOperation="open";
575     p=strrchr(lpFile,'.');
576     if (p!=NULL) {
577       x=p; /* the suffixes in the register database are lowercased */
578       while (*x) {*x=tolower(*x);x++;}
579     }
580     if (p==NULL || !strcmp(p,".exe")) {
581       p=".exe";
582       if (lpParameters) {
583         sprintf(cmd,"%s %s",lpFile,lpParameters);
584       } else {
585         strcpy(cmd,lpFile);
586       }
587     } else {
588       len=200;
589       if (RegQueryValue((HKEY)HKEY_CLASSES_ROOT,p,subclass,&len)==SHELL_ERROR_SUCCESS) {
590         if (len>20)
591           fprintf(stddeb,"ShellExecute:subclass with len %ld? (%s), please report.\n",len,subclass);
592         subclass[len]='\0';
593         strcat(subclass,"\\shell\\");
594         strcat(subclass,lpOperation);
595         strcat(subclass,"\\command");
596         dprintf_exec(stddeb,"ShellExecute:looking for %s.\n",subclass);
597         len=400;
598         if (RegQueryValue((HKEY)HKEY_CLASSES_ROOT,subclass,cmd,&len)==SHELL_ERROR_SUCCESS) {
599           char *t;
600           dprintf_exec(stddeb,"ShellExecute:...got %s\n",cmd);
601           cmd[len]='\0';
602           t=strstr(cmd,"%1");
603           if (t==NULL) {
604             strcat(cmd," ");
605             strcat(cmd,lpFile);
606           } else {
607             char *s;
608             s=xmalloc(len+strlen(lpFile)+10);
609             strncpy(s,cmd,t-cmd);
610             s[t-cmd]='\0';
611             strcat(s,lpFile);
612             strcat(s,t+2);
613             strcpy(cmd,s);
614             free(s);
615           }
616           /* does this use %x magic too? */
617           if (lpParameters) {
618             strcat(cmd," ");
619             strcat(cmd,lpParameters);
620           }
621         } else {
622           fprintf(stddeb,"ShellExecute: No %s\\shell\\%s\\command found for \"%s\" suffix.\n",subclass,lpOperation,p);
623           return (HINSTANCE)14; /* unknown type */
624         }
625       } else {
626         fprintf(stddeb,"ShellExecute: No operation found for \"%s\" suffix.\n",p);
627         return (HINSTANCE)14; /* file not found */
628       }
629     }
630     dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
631     return WinExec(cmd,iShowCmd);
632 }
633
634
635 /*************************************************************************
636  *                              FindExecutable          [SHELL.21]
637  */
638 HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
639 {
640         fprintf(stdnimp, "FindExecutable : Empty Stub !!!\n");
641         return 0;
642 }
643
644 static char AppName[128], AppMisc[906];
645
646 /*************************************************************************
647  *                              AboutDlgProc            [SHELL.33]
648  */
649 LRESULT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
650 {
651   char Template[512], AppTitle[512];
652  
653   switch(msg) {
654    case WM_INITDIALOG:
655 #ifdef WINELIB32
656     SendDlgItemMessage(hWnd,stc1,STM_SETICON,lParam,0);
657 #else
658     SendDlgItemMessage(hWnd,stc1,STM_SETICON,LOWORD(lParam),0);
659 #endif
660     GetWindowText(hWnd, Template, 511);
661     sprintf(AppTitle, Template, AppName);
662     SetWindowText(hWnd, AppTitle);
663     SetWindowText(GetDlgItem(hWnd,100), AppMisc);
664     return 1;
665     
666    case WM_COMMAND:
667     switch (wParam) {
668      case IDOK:
669       EndDialog(hWnd, TRUE);
670       return TRUE;
671     }
672     break;
673   }
674   return FALSE;
675 }
676
677 /*************************************************************************
678  *                              ShellAbout              [SHELL.22]
679  */
680 INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon)
681 {
682     HANDLE handle;
683     BOOL bRet;
684     DWORD WineProc,Win16Proc,Win32Proc;
685     static int initialized=0;
686
687     if (szApp) strncpy(AppName, szApp, sizeof(AppName));
688     else *AppName = 0;
689     AppName[sizeof(AppName)-1]=0;
690
691     if (szOtherStuff) strncpy(AppMisc, szOtherStuff, sizeof(AppMisc));
692     else *AppMisc = 0;
693     AppMisc[sizeof(AppMisc)-1]=0;
694
695     if (!hIcon) hIcon = LoadIcon(0,MAKEINTRESOURCE(OIC_WINEICON));
696     
697     if(!initialized)
698     {
699         WineProc=(DWORD)AboutDlgProc;
700         Win16Proc=(DWORD)GetWndProcEntry16("AboutDlgProc");
701         Win32Proc=(DWORD)RELAY32_GetEntryPoint(RELAY32_GetBuiltinDLL("WINPROCS32"),
702                                                "AboutDlgProc",0);
703         ALIAS_RegisterAlias(WineProc,Win16Proc,Win32Proc);
704         initialized=1;
705     }
706
707     handle = SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX );
708     if (!handle) return FALSE;
709     bRet = DialogBoxIndirectParam( WIN_GetWindowInstance( hWnd ),
710                                    handle, hWnd,
711                                    GetWndProcEntry16("AboutDlgProc"), 
712                                    (LONG)hIcon );
713     SYSRES_FreeResource( handle );
714     return bRet;
715 }
716
717 /*************************************************************************
718  *                              ExtractIcon             [SHELL.34]
719  */
720 HICON ExtractIcon(HINSTANCE hInst, LPCSTR lpszExeFileName, UINT nIconIndex)
721 {
722         HICON   hIcon = 0;
723         HINSTANCE hInst2 = hInst;
724         dprintf_reg(stddeb, "ExtractIcon(%04x, '%s', %d\n", 
725                         hInst, lpszExeFileName, nIconIndex);
726         return 0;
727         if (lpszExeFileName != NULL) {
728                 hInst2 = LoadModule(lpszExeFileName,(LPVOID)-1);
729         }
730         if (hInst2 != 0 && nIconIndex == (UINT)-1) {
731 #if 0
732                 count = GetRsrcCount(hInst2, NE_RSCTYPE_GROUP_ICON);
733                 dprintf_reg(stddeb, "ExtractIcon // '%s' has %d icons !\n", lpszExeFileName, count);
734                 return (HICON)count;
735 #endif
736         }
737         if (hInst2 != hInst && hInst2 != 0) {
738                 FreeLibrary(hInst2);
739         }
740         return hIcon;
741 }
742
743
744 /*************************************************************************
745  *                              ExtractAssociatedIcon   [SHELL.36]
746  */
747 HICON ExtractAssociatedIcon(HINSTANCE hInst,LPSTR lpIconPath, LPWORD lpiIcon)
748 {
749     dprintf_reg(stdnimp, "ExtractAssociatedIcon : Empty Stub !!!\n");
750     return 0;
751 }
752
753 /*************************************************************************
754  *              DoEnvironmentSubst      [SHELL.37]
755  */
756 DWORD DoEnvironmentSubst(LPSTR str,WORD len)
757 {
758     dprintf_reg(stdnimp, "DoEnvironmentSubst(%s,%x): Empty Stub !!!\n",str,len);
759     return 0;
760 }
761
762 /*************************************************************************
763  *                              RegisterShellHook       [SHELL.102]
764  */
765 int RegisterShellHook(void *ptr) 
766 {
767         dprintf_reg(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
768         return 0;
769 }
770
771
772 /*************************************************************************
773  *                              ShellHookProc           [SHELL.103]
774  */
775 int ShellHookProc(void) 
776 {
777         dprintf_reg(stdnimp, "ShellHookProc : Empty Stub !!!\n");
778         return 0;
779 }