Release 950606
[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 "windows.h"
9 #include "shell.h"
10 #include "neexe.h"
11 #include "selectors.h"
12 #include "../rc/sysres.h"
13 #include "dlgs.h"
14 #include "dialog.h"
15 #include "stddebug.h"
16 /* #define DEBUG_REG */
17 #include "debug.h"
18
19 LPKEYSTRUCT     lphRootKey = NULL,lphTopKey = NULL;
20
21 static char RootKeyName[]=".classes", TopKeyName[] = "(null)";
22
23 /*************************************************************************
24  *                        SHELL_RegCheckForRoot()     internal use only
25  */
26 static LONG SHELL_RegCheckForRoot()
27 {
28     HKEY hNewKey;
29
30     if (lphRootKey == NULL){
31       hNewKey = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
32       lphRootKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
33       if (lphRootKey == NULL) {
34         printf("SHELL_RegCheckForRoot: Couldn't allocate root key!\n");
35         return ERROR_OUTOFMEMORY;
36       }
37       lphRootKey->hKey = 1;
38       lphRootKey->lpSubKey = RootKeyName;
39       lphRootKey->dwType = 0;
40       lphRootKey->lpValue = NULL;
41       lphRootKey->lpSubLvl = lphRootKey->lpNextKey = lphRootKey->lpPrevKey = NULL;
42
43       hNewKey = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
44       lphTopKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
45       if (lphTopKey == NULL) {
46         printf("SHELL_RegCheckForRoot: Couldn't allocate top key!\n");
47         return ERROR_OUTOFMEMORY;
48       }
49       lphTopKey->hKey = 0;
50       lphTopKey->lpSubKey = TopKeyName;
51       lphTopKey->dwType = 0;
52       lphTopKey->lpValue = NULL;
53       lphTopKey->lpSubLvl = lphRootKey;
54       lphTopKey->lpNextKey = lphTopKey->lpPrevKey = NULL;
55
56       dprintf_reg(stddeb,"SHELL_RegCheckForRoot: Root/Top created\n");
57     }
58     return ERROR_SUCCESS;
59 }
60
61 /*************************************************************************
62  *                              RegOpenKey              [SHELL.1]
63  */
64 LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
65 {
66         LPKEYSTRUCT     lpKey;
67         LPCSTR          ptr;
68         char            str[128];
69         LONG            dwRet;
70
71         dwRet = SHELL_RegCheckForRoot();
72         if (dwRet != ERROR_SUCCESS) return dwRet;
73         dprintf_reg(stddeb, "RegOpenKey(%08lX, %p='%s', %p)\n",
74                                                 hKey, lpSubKey, lpSubKey, lphKey);
75         if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
76         if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
77         switch(hKey) {
78         case 0: 
79           lpKey = lphTopKey; break;
80         case HKEY_CLASSES_ROOT: /* == 1 */
81           lpKey = lphRootKey; break;
82         default: 
83           dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", hKey);
84           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
85         }
86         if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
87         while(*lpSubKey) {
88           ptr = strchr(lpSubKey,'\\');
89           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
90           strncpy(str,lpSubKey,ptr-lpSubKey);
91           str[ptr-lpSubKey] = 0;
92           lpSubKey = ptr; 
93           if (*lpSubKey) lpSubKey++;
94           
95           lpKey = lpKey->lpSubLvl;
96           while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { lpKey = lpKey->lpNextKey; }
97           if (lpKey == NULL) {
98             dprintf_reg(stddeb,"RegOpenKey: key %s not found!\n",str);
99             return ERROR_BADKEY;
100           }         
101         }
102         *lphKey = lpKey->hKey;
103         return ERROR_SUCCESS;
104 }
105
106
107 /*************************************************************************
108  *                              RegCreateKey            [SHELL.2]
109  */
110 LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
111 {
112         HKEY            hNewKey;
113         LPKEYSTRUCT     lpNewKey;
114         LPKEYSTRUCT     lpKey;
115         LPKEYSTRUCT     lpPrevKey;
116         LONG            dwRet;
117         LPCSTR          ptr;
118         char            str[128];
119
120         dwRet = SHELL_RegCheckForRoot();
121         if (dwRet != ERROR_SUCCESS) return dwRet;
122         dprintf_reg(stddeb, "RegCreateKey(%08lX, '%s', %p)\n",  hKey, lpSubKey, lphKey);
123         if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
124         if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
125         switch(hKey) {
126         case 0: 
127           lpKey = lphTopKey; break;
128         case HKEY_CLASSES_ROOT: /* == 1 */
129           lpKey = lphRootKey; break;
130         default: 
131           dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", hKey);
132           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
133         }
134         if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
135         while (*lpSubKey) {
136           dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
137           ptr = strchr(lpSubKey,'\\');
138           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
139           strncpy(str,lpSubKey,ptr-lpSubKey);
140           str[ptr-lpSubKey] = 0;
141           lpSubKey = ptr; 
142           if (*lpSubKey) lpSubKey++;
143           
144           lpPrevKey = lpKey;
145           lpKey = lpKey->lpSubLvl;
146           while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
147             lpKey = lpKey->lpNextKey; 
148           }
149           if (lpKey == NULL) {
150             hNewKey = GlobalAlloc(GMEM_MOVEABLE, sizeof(KEYSTRUCT));
151             lpNewKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
152             if (lpNewKey == NULL) {
153               printf("RegCreateKey // Can't alloc new key !\n");
154               return ERROR_OUTOFMEMORY;
155             }
156             lpNewKey->hKey = hNewKey;
157             lpNewKey->lpSubKey = malloc(strlen(str) + 1);
158             if (lpNewKey->lpSubKey == NULL) {
159               printf("RegCreateKey // Can't alloc key string !\n");
160               return ERROR_OUTOFMEMORY;
161             }
162             strcpy(lpNewKey->lpSubKey, str);
163             lpNewKey->lpNextKey = lpPrevKey->lpSubLvl;
164             lpNewKey->lpPrevKey = NULL;
165             lpPrevKey->lpSubLvl = lpNewKey;
166
167             lpNewKey->dwType = 0;
168             lpNewKey->lpValue = NULL;
169             lpNewKey->lpSubLvl = NULL;
170             *lphKey = hNewKey;
171             dprintf_reg(stddeb,"RegCreateKey // successful '%s' key=%08lX !\n", str, hNewKey);
172             lpKey = lpNewKey;
173           } else {
174             *lphKey = lpKey->hKey;
175             dprintf_reg(stddeb,"RegCreateKey // found '%s', key=%08lX\n", str, *lphKey);
176           }
177         }
178         return ERROR_SUCCESS;
179 }
180
181
182 /*************************************************************************
183  *                              RegCloseKey             [SHELL.3]
184  */
185 LONG RegCloseKey(HKEY hKey)
186 {
187         dprintf_reg(stdnimp, "EMPTY STUB !!! RegCloseKey(%08lX);\n", hKey);
188         return ERROR_INVALID_PARAMETER;
189 }
190
191
192 /*************************************************************************
193  *                              RegDeleteKey            [SHELL.4]
194  */
195 LONG RegDeleteKey(HKEY hKey, LPCSTR lpSubKey)
196 {
197         dprintf_reg(stdnimp, "EMPTY STUB !!! RegDeleteKey(%08lX, '%s');\n", 
198                                                                                                 hKey, lpSubKey);
199         return ERROR_INVALID_PARAMETER;
200 }
201
202
203 /*************************************************************************
204  *                              RegSetValue             [SHELL.5]
205  */
206 LONG RegSetValue(HKEY hKey, LPCSTR lpSubKey, DWORD dwType, 
207                                         LPCSTR lpVal, DWORD dwIgnored)
208 {
209         HKEY            hRetKey;
210         LPKEYSTRUCT     lpKey;
211         LONG            dwRet;
212         dprintf_reg(stddeb, "RegSetValue(%08lX, '%s', %08lX, '%s', %08lX);\n",
213                                                 hKey, lpSubKey, dwType, lpVal, dwIgnored);
214         if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
215         if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
216         if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
217                 dprintf_reg(stddeb, "RegSetValue // key not found ... so create it !\n");
218                 if ((dwRet = RegCreateKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
219                         fprintf(stderr, "RegSetValue // key creation error %08lX !\n", dwRet);
220                         return dwRet;
221                         }
222                 }
223         lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
224         if (lpKey == NULL) return ERROR_BADKEY;
225         if (lpKey->lpValue != NULL) free(lpKey->lpValue);
226         lpKey->lpValue = malloc(strlen(lpVal) + 1);
227         strcpy(lpKey->lpValue, lpVal);
228         dprintf_reg(stddeb,"RegSetValue // successful key='%s' val='%s' !\n", lpSubKey, lpKey->lpValue);
229         return ERROR_SUCCESS;
230 }
231
232
233 /*************************************************************************
234  *                              RegQueryValue           [SHELL.6]
235  */
236 LONG RegQueryValue(HKEY hKey, LPCSTR lpSubKey, LPSTR lpVal, LONG FAR *lpcb)
237 {
238         HKEY            hRetKey;
239         LPKEYSTRUCT     lpKey;
240         LONG            dwRet;
241         int                     size;
242         dprintf_reg(stddeb, "RegQueryValue(%08lX, '%s', %p, %p);\n",
243                                                         hKey, lpSubKey, lpVal, lpcb);
244         if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
245         if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
246         if (lpcb == NULL) return ERROR_INVALID_PARAMETER;
247         if (!*lpcb) return ERROR_INVALID_PARAMETER;
248
249         if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
250                 fprintf(stderr, "RegQueryValue // key not found !\n");
251                 return dwRet;
252                 }
253         lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
254         if (lpKey == NULL) return ERROR_BADKEY;
255         if (lpKey->lpValue != NULL) {
256           if ((size = strlen(lpKey->lpValue)+1) > *lpcb){
257             strncpy(lpVal,lpKey->lpValue,*lpcb-1);
258             lpVal[*lpcb-1] = 0;
259           } else {
260             strcpy(lpVal,lpKey->lpValue);
261             *lpcb = size;
262           }
263         } else {
264           *lpVal = 0;
265           *lpcb = (LONG)1;
266         }
267         dprintf_reg(stddeb,"RegQueryValue // return '%s' !\n", lpVal);
268         return ERROR_SUCCESS;
269 }
270
271
272 /*************************************************************************
273  *                              RegEnumKey              [SHELL.7]
274  */
275 LONG RegEnumKey(HKEY hKey, DWORD dwSubKey, LPSTR lpBuf, DWORD dwSize)
276 {
277         LPKEYSTRUCT     lpKey;
278         LONG            dwRet;
279         LONG            len;
280
281         dwRet = SHELL_RegCheckForRoot();
282         if (dwRet != ERROR_SUCCESS) return dwRet;
283         dprintf_reg(stddeb, "RegEnumKey(%08lX, %ld)\n", hKey, dwSubKey);
284         if (lpBuf == NULL) return ERROR_INVALID_PARAMETER;
285         switch(hKey) {
286         case 0: 
287           lpKey = lphTopKey; break;
288         case HKEY_CLASSES_ROOT: /* == 1 */
289           lpKey = lphRootKey; break;
290         default: 
291           dprintf_reg(stddeb,"RegEnumKey // specific key = %08lX !\n", hKey);
292           lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
293         }
294
295         lpKey = lpKey->lpSubLvl;
296         while(lpKey != NULL){
297           if (!dwSubKey){
298             len = min(dwSize-1,strlen(lpKey->lpSubKey));
299             strncpy(lpBuf,lpKey->lpSubKey,len);
300             lpBuf[len] = 0;
301             dprintf_reg(stddeb, "RegEnumKey: found %s\n",lpBuf);
302             return ERROR_SUCCESS;
303           }
304           dwSubKey--;
305           lpKey = lpKey->lpNextKey;
306         }
307         dprintf_reg(stddeb, "RegEnumKey: key not found!\n");
308         return ERROR_INVALID_PARAMETER;
309 }
310
311 /*************************************************************************
312  *                              DragAcceptFiles         [SHELL.9]
313  */
314 void DragAcceptFiles(HWND hWnd, BOOL b)
315 {
316         fprintf(stdnimp, "DragAcceptFiles : Empty Stub !!!\n");
317 }
318
319
320 /*************************************************************************
321  *                              DragQueryFile           [SHELL.11]
322  */
323 void DragQueryFile(HDROP h, UINT u, LPSTR u2, UINT u3)
324 {
325         fprintf(stdnimp, "DragQueryFile : Empty Stub !!!\n");
326
327 }
328
329
330 /*************************************************************************
331  *                              DragFinish              [SHELL.12]
332  */
333 void DragFinish(HDROP h)
334 {
335         fprintf(stdnimp, "DragFinish : Empty Stub !!!\n");
336 }
337
338
339 /*************************************************************************
340  *                              DragQueryPoint          [SHELL.13]
341  */
342 BOOL DragQueryPoint(HDROP h, POINT FAR *p)
343 {
344         fprintf(stdnimp, "DragQueryPoint : Empty Stub !!!\n");
345         return FALSE;
346 }
347
348
349 /*************************************************************************
350  *                              ShellExecute            [SHELL.20]
351  */
352 HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd)
353 {
354         fprintf(stdnimp, "ShellExecute: empty stub\n");
355         return 2;
356         fprintf(stdnimp, "ShellExecute // hWnd=%04X\n", hWnd);  
357         fprintf(stdnimp, "ShellExecute // lpOperation='%s'\n", lpOperation);
358         fprintf(stdnimp, "ShellExecute // lpFile='%s'\n", lpFile);
359         fprintf(stdnimp, "ShellExecute // lpParameters='%s'\n", lpParameters);
360         fprintf(stdnimp, "ShellExecute // lpDirectory='%s'\n", lpDirectory);
361         fprintf(stdnimp, "ShellExecute // iShowCmd=%04X\n", iShowCmd);
362         return 2; /* file not found */
363 }
364
365
366 /*************************************************************************
367  *                              FindExecutable          [SHELL.21]
368  */
369 HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
370 {
371         fprintf(stdnimp, "FindExecutable : Empty Stub !!!\n");
372         return 0;
373 }
374
375 static char AppName[512], AppMisc[512];
376
377 /*************************************************************************
378  *                              AboutDlgProc            [SHELL.33]
379  */
380 INT AboutDlgProc(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
381 {
382   switch(msg) {
383    case WM_INITDIALOG:
384     SendDlgItemMessage(hWnd,stc1,STM_SETICON,LOWORD(lParam),0);
385     SetWindowText(hWnd, AppName);
386     SetWindowText(GetDlgItem(hWnd,100), AppMisc);
387     return 1;
388     
389    case WM_COMMAND:
390     switch (wParam) {
391      case IDOK:
392       EndDialog(hWnd, TRUE);
393       return TRUE;
394     }
395     break;
396   }
397   return FALSE;
398 }
399
400 /*************************************************************************
401  *                              ShellAbout              [SHELL.22]
402  */
403 INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon)
404 {
405   if (szApp) {
406     sprintf(AppName, "About %s", szApp);
407   } else  {
408     *AppName = 0;
409   }
410   if (szOtherStuff) {
411     strcpy(AppMisc, szOtherStuff);
412   } else {
413     *AppMisc = 0;
414   }
415   if (!hIcon) {
416     hIcon = LoadIcon(0,MAKEINTRESOURCE(OIC_WINEICON));
417   }
418   return DialogBoxIndirectParamPtr(GetWindowWord(hWnd, GWW_HINSTANCE),
419                                    sysres_DIALOG_SHELL_ABOUT_MSGBOX,
420                                    hWnd, GetWndProcEntry16("AboutDlgProc"),
421                                    hIcon);
422 }
423
424 /*************************************************************************
425  *                              ExtractIcon             [SHELL.34]
426  */
427 HICON ExtractIcon(HINSTANCE hInst, LPCSTR lpszExeFileName, UINT nIconIndex)
428 {
429         HICON   hIcon = 0;
430         HINSTANCE hInst2 = hInst;
431         dprintf_reg(stddeb, "ExtractIcon(%04X, '%s', %d\n", 
432                         hInst, lpszExeFileName, nIconIndex);
433         if (lpszExeFileName != NULL) {
434                 hInst2 = LoadLibrary(lpszExeFileName);
435         }
436         if (hInst2 != 0 && nIconIndex == (UINT)-1) {
437 #if 0
438                 count = GetRsrcCount(hInst2, NE_RSCTYPE_GROUP_ICON);
439                 dprintf_reg(stddeb, "ExtractIcon // '%s' has %d icons !\n", lpszExeFileName, count);
440                 return (HICON)count;
441 #endif
442         }
443         if (hInst2 != hInst && hInst2 != 0) {
444                 FreeLibrary(hInst2);
445         }
446         return hIcon;
447 }
448
449
450 /*************************************************************************
451  *                              ExtractAssociatedIcon   [SHELL.36]
452  */
453 HICON ExtractAssociatedIcon(HINSTANCE hInst,LPSTR lpIconPath, LPWORD lpiIcon)
454 {
455     dprintf_reg(stdnimp, "ExtractAssociatedIcon : Empty Stub !!!\n");
456     return 0;
457 }
458
459 /*************************************************************************
460  *              DoEnvironmentSubst      [SHELL.37]
461  */
462 DWORD DoEnvironmentSubst(LPSTR str,WORD len)
463 {
464     dprintf_reg(stdnimp, "DoEnvironmentSubst(%s,%x): Empyt Stub !!!\n",str,len);
465     return 0;
466 }
467
468 /*************************************************************************
469  *                              RegisterShellHook       [SHELL.102]
470  */
471 int RegisterShellHook(void *ptr) 
472 {
473         dprintf_reg(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
474         return 0;
475 }
476
477
478 /*************************************************************************
479  *                              ShellHookProc           [SHELL.103]
480  */
481 int ShellHookProc(void) 
482 {
483         dprintf_reg(stdnimp, "ShellHookProc : Empty Stub !!!\n");
484         return 0;
485 }