Release 980104
[wine] / misc / shellord.c
1 /*
2  *                              Shell Ordinal Functions
3  *
4  * These are completely undocumented. The meaning of the functions changes
5  * between different OS versions (NT uses Unicode strings, 95 uses ASCII
6  * strings, etc. etc.)
7  * 
8  * They are just here so that explorer.exe and iexplore.exe can be tested.
9  *
10  * Copyright 1997 Marcus Meissner
11  */
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <ctype.h>
17 #include "windows.h"
18 #include "file.h"
19 #include "shell.h"
20 #include "heap.h"
21 #include "module.h"
22 #include "neexe.h"
23 #include "resource.h"
24 #include "dlgs.h"
25 #include "win.h"
26 #include "graphics.h"
27 #include "cursoricon.h"
28 #include "interfaces.h"
29 #include "shlobj.h"
30 #include "stddebug.h"
31 #include "debug.h"
32 #include "winreg.h"
33
34 /*************************************************************************
35  *                       SHELL32_2                      [SHELL32.2]
36  */
37 DWORD WINAPI SHELL32_2(HWND32 hwnd,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
38         fprintf(stderr,"SHELL32_2(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",
39                 hwnd,x2,x3,x4,x5,x6
40         );
41         return 0;
42 }
43 /*************************************************************************
44  *                       SHELL32_16                     [SHELL32.16]
45  * find_lastitem_in_itemidlist()
46  */
47 LPSHITEMID WINAPI SHELL32_16(LPITEMIDLIST iil) {
48         LPSHITEMID      lastsii,sii;
49
50         if (!iil)
51                 return NULL;
52         sii = &(iil->mkid);
53         lastsii = sii;
54         while (sii->cb) {
55                 lastsii = sii;
56                 sii = (LPSHITEMID)(((char*)sii)+sii->cb);
57         }
58         return lastsii;
59 }
60 /*************************************************************************
61  *                       SHELL32_29                     [SHELL32.29]
62  * is_rootdir(const char*path)
63  */
64 BOOL32 WINAPI SHELL32_29(LPCSTR x) {
65         if (!lstrcmp32A(x+1,":\\"))             /* "X:\" */
66                 return 1;
67         if (!lstrcmp32A(x,"\\"))                /* "\" */
68                 return 1;
69         if (x[0]=='\\' && x[1]=='\\') {         /* UNC "\\<xx>\" */
70                 int     foundbackslash = 0;
71                 x=x+2;
72                 while (*x) {
73                         if (*x++=='\\')
74                                 foundbackslash++;
75                 }
76                 if (foundbackslash<=1)  /* max 1 \ more ... */
77                         return 1;
78         }
79         return 0;
80 }
81
82 /*************************************************************************
83  *                       SHELL32_30                     [SHELL32.30]
84  * get_rootdir(char*path,int drive)
85  */
86 LPSTR WINAPI SHELL32_30(LPSTR root,BYTE drive) {
87         strcpy(root,"A:\\");
88         root[0]+=drive;
89         return root;
90 }
91
92 /*************************************************************************
93  *                                      SHELL32_31      [SHELL32.31]
94  * returns pointer to last . in last pathcomponent or at \0.
95  */
96 LPSTR WINAPI SHELL32_31(LPSTR path) {
97     LPSTR   lastpoint = NULL;
98
99     while (*path) {
100         if (*path=='\\'||*path==' ')
101             lastpoint=NULL;
102         if (*path=='.')
103             lastpoint=path;
104         path++;
105     }
106     return lastpoint?lastpoint:path;
107 }
108
109 /*************************************************************************
110  *                              SHELL32_32      [SHELL32.32]
111  * append \ if there is none
112  */
113 LPSTR WINAPI SHELL32_32(LPSTR path) {
114     int len;
115
116     len = lstrlen32A(path);
117     if (len && path[len-1]!='\\') {
118         path[len+0]='\\';
119         path[len+1]='\0';
120         return path+len+1;
121     } else
122         return path+len;
123 }
124
125 /*************************************************************************
126  *                              SHELL32_33      [SHELL32.33]
127  * remove spaces from beginning and end of passed string
128  */
129 LPSTR WINAPI SHELL32_33(LPSTR str) {
130     LPSTR x = str;
131
132     while (*x==' ') x++;
133     if (x!=str)
134         lstrcpy32A(str,x);
135     if (!*str)
136         return str;
137     x=str+strlen(str)-1;
138     while (*x==' ')
139         x--;
140     if (*x==' ')
141         *x='\0';
142     return x;
143 }
144
145
146 /*************************************************************************
147  *                              SHELL32_34      [SHELL32.34]
148  * basename(char *fn);
149  */
150 LPSTR WINAPI SHELL32_34(LPSTR fn) {
151     LPSTR basefn;
152
153     basefn = fn;
154     while (fn[0]) {
155         if (((fn[0]=='\\') || (fn[0]==':')) && fn[1] && fn[1]!='\\')
156             basefn = fn+1;
157         fn++;
158     }
159     return basefn;
160 }
161
162 /*************************************************************************
163  *                       SHELL32_35                     [SHELL32.35]
164  * bool getpath(char *pathname); truncates passed argument to a valid path
165  * returns if the string was modified or not.
166  * "\foo\xx\foo"-> "\foo\xx"
167  * "\"          -> "\"
168  * "a:\foo"     -> "a:\"
169  */
170 DWORD WINAPI SHELL32_35(LPSTR fn) {
171         LPSTR   x,cutplace;
172
173         if (!fn[0])
174                 return 0;
175         x=fn;
176         cutplace = fn;
177         while (*x) {
178                 if (*x=='\\') {
179                         cutplace=x++;
180                         continue;
181                 }
182                 if (*x==':') {
183                         x++;
184                         if (*x=='\\')
185                                 cutplace=++x;
186                         continue; /* already x++ed */
187                 }
188                 x++;
189         }
190         if (!*cutplace)
191                 return 0;
192         if (cutplace==fn) {
193                 if (fn[0]=='\\') {
194                         if (!fn[1])
195                                 return 0;
196                         fn[0]='\0';
197                         return 1;
198                 }
199         }
200         *cutplace='\0';
201         return 1;
202 }
203
204 /*************************************************************************
205  *                              SHELL32_37      [SHELL32.37]
206  * concat_paths(char*target,const char*add);
207  * concats "target\\add" and writes them to target
208  */
209 LPSTR WINAPI SHELL32_37(LPSTR target,LPSTR x1,LPSTR x2) {
210         char    buf[260];
211
212         if (!x2 || !x2[0]) {
213                 lstrcpy32A(target,x1);
214                 return target;
215         }
216         lstrcpy32A(buf,x1);
217         SHELL32_32(buf); /* append \ if not there */
218         lstrcat32A(buf,x2);
219         lstrcpy32A(target,buf);
220         return target;
221 }
222
223 /*************************************************************************
224  *                              SHELL32_36      [SHELL32.36]
225  * concat_paths(char*target,const char*add);
226  * concats "target\\add" and writes them to target
227  */
228 LPSTR WINAPI SHELL32_36(LPSTR x1,LPSTR x2) {
229         while (x2[0]=='\\') x2++;
230         return SHELL32_37(x1,x1,x2);
231 }
232
233 /*************************************************************************
234  *                              SHELL32_39      [SHELL32.39]
235  * isUNC(const char*path);
236  */
237 BOOL32 WINAPI SHELL32_39(LPCSTR path) {
238         if ((path[0]=='\\') && (path[1]=='\\'))
239                 return TRUE;
240         return FALSE;
241 }
242
243 /*************************************************************************
244  *                              SHELL32_45      [SHELL32.45]
245  * file_exists(char *fn);
246  */
247 BOOL32 WINAPI SHELL32_45(LPSTR fn) {
248     if (GetFileAttributes32A(fn)==-1)
249         return FALSE;
250     else
251         return TRUE;
252 }
253
254 /*************************************************************************
255  *                              SHELL32_52      [SHELL32.52]
256  * look for next arg in string. handle "quoted" strings
257  * returns pointer to argument *AFTER* the space. Or to the \0.
258  */
259 LPSTR WINAPI SHELL32_52(LPSTR cmdline) {
260     BOOL32      qflag = FALSE;
261
262     while (*cmdline) {
263         if ((*cmdline==' ') && !qflag)
264                 return cmdline+1;
265         if (*cmdline=='"')
266                 qflag=!qflag;
267         cmdline++;
268     }
269     return cmdline;
270 }
271
272 /*************************************************************************
273  *                              SHELL32_56      [SHELL32.56]
274  * unquote string (remove ")
275  */
276 VOID WINAPI SHELL32_56(LPSTR str) {
277     DWORD      len = lstrlen32A(str);
278
279     if (*str!='"') return;
280     if (str[len-1]!='"') return;
281     str[len-1]='\0';
282     lstrcpy32A(str,str+1);
283     return;
284 }
285
286 /*************************************************************************
287  *                       SHELL32_58                     [SHELL32.58]
288  */
289 DWORD WINAPI SHELL32_58(LPCSTR src,DWORD x2,LPSTR target,DWORD pathlen) {
290         fprintf(stderr,"SHELL32_58(%s,0x%08lx,%p,%ld),STUB!\n",
291                 src,x2,target,pathlen
292         );
293         if (!src)
294                 return 0;
295         return 0;
296 }
297
298 /*************************************************************************
299  *                       SHELL32_62                     [SHELL32.62]
300  */
301 DWORD WINAPI SHELL32_62(DWORD x,DWORD y,DWORD z,DWORD a) {
302         fprintf(stderr,"SHELL32_62(%08lx,%08lx,%08lx,%08lx),stub!\n",x,y,z,a);
303         return 0xffffffff;
304 }
305
306 /*************************************************************************
307  *                      SHELL32_63                     [SHELL32.63]
308  */
309 DWORD WINAPI SHELL32_63(HWND32 howner, LPSTR targetbuf, DWORD len, DWORD x, LPCSTR suffix, LPCSTR y, LPCSTR cmd) {
310     fprintf(stderr,"SHELL32_63(%04x,%p,%ld,%08lx,%s,%s,%s),stub!\n",
311             howner,targetbuf,len,x,suffix,y,cmd
312     );
313     /* puts up a Open Dialog and requests input into targetbuf */
314     /* OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_FILEMUSTEXIST|OFN_unknown */
315     lstrcpy32A(targetbuf,"x:\\s3.exe");
316     return 1;
317 }
318
319 /*************************************************************************
320  *                      SHELL32_68                     [SHELL32.68]
321  */
322 DWORD WINAPI SHELL32_68(DWORD x,DWORD y,DWORD z) {
323         fprintf(stderr,"SHELL32_68(0x%08lx,0x%08lx,0x%08lx),stub!\n",
324                 x,y,z
325         );
326         return 0;
327 }
328 /*************************************************************************
329  *                       SHELL32_71                     [SHELL32.71]
330  * returns internal shell values in the passed pointers
331  */
332 BOOL32 WINAPI SHELL32_71(LPDWORD x,LPDWORD y) {
333
334         fprintf(stderr,"SHELL32_71(%p,%p),stub!\n",x,y);
335         return TRUE;
336 }
337
338 /*************************************************************************
339  *                       SHELL32_72                     [SHELL32.72]
340  * dunno. something with icons
341  */
342 void WINAPI SHELL32_72(LPSTR x,DWORD y,DWORD z) {
343         fprintf(stderr,"SHELL32_72(%s,%08lx,%08lx),stub!\n",x,y,z);
344 }
345
346 /*************************************************************************
347  *                       SHELL32_89                     [SHELL32.89]
348  */
349 DWORD WINAPI SHELL32_89(DWORD x1,DWORD x2,DWORD x3) {
350         fprintf(stderr,"SHELL32_89(0x%08lx,0x%08lx,0x%08lx),stub!\n",
351                 x1,x2,x3
352         );
353         return 0;
354 }
355
356 /*************************************************************************
357  *                              SHELL32_119     [SHELL32.119]
358  * unknown
359  */
360 void WINAPI SHELL32_119(LPVOID x) {
361     fprintf(stderr,"SHELL32_119(%p(%s)),stub\n",x,(char *)x);
362 }
363
364 /*************************************************************************
365  *                              SHELL32_175     [SHELL32.175]
366  * unknown
367  */
368 void WINAPI SHELL32_175(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
369     fprintf(stdnimp,"SHELL32_175(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub\n",
370         x1,x2,x3,x4
371     );
372 }
373
374 /*************************************************************************
375  *                              SHELL32_181     [SHELL32.181]
376  * unknown
377  */
378 void WINAPI SHELL32_181(DWORD x,DWORD y) {
379     fprintf(stderr,"SHELL32_181(0x%08lx,0x%08lx)\n",x,y);
380 }
381
382 /*************************************************************************
383  *                              SHELL32_75      [SHELL32.75]
384  * unknown
385  */
386 BOOL32 WINAPI SHELL32_75(LPDWORD x,LPDWORD y) {
387     fprintf(stderr,"SHELL32_75(%p,%p),stub\n",x,y);
388     return TRUE;
389 }
390
391 /*************************************************************************
392  *                       SHELL32_77                     [SHELL32.77]
393  */
394 DWORD WINAPI SHELL32_77(DWORD x,DWORD y,DWORD z) {
395         fprintf(stderr,"SHELL32_77(%08lx,%08lx,%08lx),stub!\n",x,y,z);
396         return 0;
397 }
398
399 /*************************************************************************
400  *                       SHELL32_79                     [SHELL32.79]
401  * create_directory_and_notify(...)
402  */
403 DWORD WINAPI SHELL32_79(LPCSTR dir,LPVOID xvoid) {
404         fprintf(stderr,"mkdir %s,%p\n",dir,xvoid);
405         if (!CreateDirectory32A(dir,xvoid))
406                 return FALSE;
407         /* SHChangeNotify(8,1,dir,0); */
408         return TRUE;
409 }
410
411 static FARPROC32 _find_moduleproc(LPSTR dllname,HMODULE32 *xhmod,LPSTR name) {
412         HMODULE32       hmod;
413         FARPROC32       dllunload,nameproc;
414
415         if (xhmod) *xhmod = 0;
416         if (!lstrcmpi32A(SHELL32_34(dllname),"shell32.dll"))
417                 return (FARPROC32)SHELL32_DllGetClassObject;
418
419         hmod = LoadLibraryEx32A(dllname,0,LOAD_WITH_ALTERED_SEARCH_PATH);
420         if (!hmod)
421                 return NULL;
422         dllunload = GetProcAddress32(hmod,"DllCanUnloadNow");
423         if (!dllunload)
424                 if (xhmod) *xhmod = hmod;
425         nameproc = GetProcAddress32(hmod,name);
426         if (!nameproc) {
427                 FreeLibrary32(hmod);
428                 return NULL;
429         }
430         /* register unloadable dll with unloadproc ... */
431         return nameproc;
432 }
433
434 static DWORD _get_instance(REFCLSID clsid,LPSTR dllname,
435         LPVOID  unknownouter,REFIID refiid,LPVOID inst
436 ) {
437         DWORD   WINAPI  (*dllgetclassob)(REFCLSID,REFIID,LPVOID);
438         DWORD           hres;
439 /*
440         LPCLASSFACTORY  classfac;
441  */
442
443         dllgetclassob = (DWORD(*)(REFCLSID,REFIID,LPVOID))_find_moduleproc(dllname,NULL,"DllGetClassObject");
444         if (!dllgetclassob)
445                 return 0x80070000|GetLastError();
446
447 /* FIXME */
448         hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,inst);
449         if (hres<0)
450                 return hres;
451
452 /*
453         hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,&classfac);
454         if (hres<0)
455                 return hres;
456         classfac->lpvtbl->fnCreateInstance(classfac,unknownouter,refiid,inst);
457         classfac->lpvtbl->fnRelease(classfac);
458  */
459         return 0;
460 }
461 /*************************************************************************
462  *                              SHELL32_102     [SHELL32.102]
463  * unknown
464  */
465 LRESULT WINAPI SHELL32_102(
466         LPSTR aclsid,CLSID *clsid,LPUNKNOWN unknownouter,REFIID refiid,LPVOID inst
467 ) {
468         char    buffer[256],xclsid[48],xiid[48],path[260],tmodel[100];
469         HKEY    inprockey;
470         DWORD   pathlen,type,tmodellen;
471         DWORD   hres;
472         
473         StringFromCLSID(refiid,xiid);
474
475         if (clsid)
476                 StringFromCLSID(clsid,xclsid);
477         else {
478                 if (!aclsid)
479                     return 0x80040154;
480                 strcpy(xclsid,aclsid);
481         }
482         fprintf(stderr,"SHELL32_102(%p,%s,%p,%s,%p)\n",
483                 aclsid,xclsid,unknownouter,xiid,inst
484         );
485
486         sprintf(buffer,"CLSID\\%s\\InProcServer32",xclsid);
487         if (RegOpenKeyEx32A(HKEY_CLASSES_ROOT,buffer,0,0x02000000,&inprockey))
488                 return _get_instance(clsid,"shell32.dll",unknownouter,refiid,inst);
489         pathlen=sizeof(path);
490         if (RegQueryValue32A(inprockey,NULL,path,&pathlen)) {
491                 RegCloseKey(inprockey);
492                 return _get_instance(clsid,"shell32.dll",unknownouter,refiid,inst);
493         }
494         fprintf(stderr,"        -> server dll is %s\n",path);
495         tmodellen=sizeof(tmodel);
496         type=REG_SZ;
497         if (RegQueryValueEx32A(inprockey,"ThreadingModel",NULL,&type,tmodel,&tmodellen)) {
498                 RegCloseKey(inprockey);
499                 return _get_instance(clsid,"shell32.dll",unknownouter,refiid,inst);
500         }
501         fprintf(stderr,"        -> threading model is %s\n",tmodel);
502         hres=_get_instance(clsid,path,unknownouter,refiid,inst);
503         if (hres<0)
504                 hres=_get_instance(clsid,"shell32.dll",unknownouter,refiid,inst);
505         RegCloseKey(inprockey);
506         return hres;
507 }
508
509
510 /*************************************************************************
511  *                       SHELL32_183                    [SHELL32.183]
512  * Format and output errormessage.
513  */
514 void __cdecl SHELL32_183(HMODULE32 hmod,HWND32 hwnd,DWORD id,DWORD x,DWORD type,LPVOID arglist) {
515         char    buf[100],buf2[100],*buf3;
516         LPVOID  args = &arglist;
517
518         if (!LoadString32A(hmod,x,buf,100))
519                 strcpy(buf,"Desktop");
520         LoadString32A(hmod,id,buf2,100);
521         /* FIXME: the varargs handling doesn't. */
522         FormatMessage32A(0x500,buf2,0,0,&buf3,256,&args);
523
524         fprintf(stderr,"SHELL32_183(%08lx,%08lx,%08lx(%s),%08lx(%s),%08lx,%p),stub!\n",
525                 (DWORD)hmod,(DWORD)hwnd,id,buf2,x,buf,type,arglist
526         );
527         MessageBox32A(hwnd,buf3,buf,id|0x10000);
528 }
529
530
531 /*************************************************************************
532  *                       SHELL32_100                    [SHELL32.100]
533  * walks through policy table, queries <app> key, <type> value, returns 
534  * queried (DWORD) value.
535  * {0x00001,Explorer,NoRun}
536  * {0x00002,Explorer,NoClose}
537  * {0x00004,Explorer,NoSaveSettings}
538  * {0x00008,Explorer,NoFileMenu}
539  * {0x00010,Explorer,NoSetFolders}
540  * {0x00020,Explorer,NoSetTaskbar}
541  * {0x00040,Explorer,NoDesktop}
542  * {0x00080,Explorer,NoFind}
543  * {0x00100,Explorer,NoDrives}
544  * {0x00200,Explorer,NoDriveAutoRun}
545  * {0x00400,Explorer,NoDriveTypeAutoRun}
546  * {0x00800,Explorer,NoNetHood}
547  * {0x01000,Explorer,NoStartBanner}
548  * {0x02000,Explorer,RestrictRun}
549  * {0x04000,Explorer,NoPrinterTabs}
550  * {0x08000,Explorer,NoDeletePrinter}
551  * {0x10000,Explorer,NoAddPrinter}
552  * {0x20000,Explorer,NoStartMenuSubFolders}
553  * {0x40000,Explorer,MyDocsOnNet}
554  * {0x80000,WinOldApp,NoRealMode}
555  */
556 DWORD WINAPI SHELL32_100(DWORD pol) {
557         HKEY    xhkey;
558
559         fprintf(stderr,"SHELL32_100(%08lx),stub!\n",pol);
560         if (RegOpenKey32A(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Policies",&xhkey))
561                 return 0;
562         /* FIXME: do nothing for now, just return 0 (== "allowed") */
563         RegCloseKey(xhkey);
564         return 0;
565         
566 }
567
568 /*************************************************************************
569  *                       SHELL32_152                    [SHELL32.152]
570  * itemlist_length
571  */
572 DWORD WINAPI SHELL32_152(LPITEMIDLIST iil) {
573         LPSHITEMID      si;
574         DWORD           len;
575
576         si = &(iil->mkid);
577         len = 2;
578         while (si->cb) {
579                 len     += si->cb;
580                 si       = (LPSHITEMID)(((char*)si)+si->cb);
581         }
582         return len;
583 }
584
585 /*************************************************************************
586  *                      SHELL32_158                    [SHELL32.158]
587  */
588 LPSTR WINAPI SHELL32_158(LPSTR path,DWORD y,DWORD z) {
589     fprintf(stderr,"SHELL32_158(%s,%08lx,%08lx)\n",path,y,z);
590     path = SHELL32_31(path);
591     return *path?(path+1):path;
592 }
593
594 /*************************************************************************
595  *                       SHELL32_165                    [SHELL32.165]
596  * create_path_and_notify(...)
597  */
598 DWORD WINAPI SHELL32_165(DWORD x,LPCSTR path) {
599         if (SHELL32_79(path,(LPVOID)x))
600                 return 0;
601         fprintf(stderr,"SHELL32_165(%08lx,%s),stub!\n",x,path);
602         return 0;
603 }
604
605 /*************************************************************************
606  *                       SHELL32_195                    [SHELL32.195]
607  * free_ptr() - frees memory using IMalloc
608  */
609 DWORD WINAPI SHELL32_195(LPVOID x) {
610         return LocalFree32((HANDLE32)x);
611 }
612
613 /*************************************************************************
614  *                       SHELL32_196                    [SHELL32.196]
615  * void *task_alloc(DWORD len), uses SHMalloc allocator
616  */
617 LPVOID WINAPI SHELL32_196(DWORD len) {
618         return (LPVOID)LocalAlloc32(len,LMEM_ZEROINIT); /* FIXME */
619 }
620
621 /*************************************************************************
622  *                       SHELL32_18                     [SHELL32.18]
623  * copy_itemidlist()
624  */
625 LPITEMIDLIST WINAPI SHELL32_18(LPITEMIDLIST iil) {
626         DWORD           len;
627         LPITEMIDLIST    newiil;
628
629         len = SHELL32_152(iil);
630         newiil = (LPITEMIDLIST)SHELL32_196(len);
631         memcpy(newiil,iil,len);
632         return newiil;
633 }
634
635 /*************************************************************************
636  *                       SHELL32_25                     [SHELL32.25]
637  * merge_itemidlist()
638  */
639 LPITEMIDLIST WINAPI SHELL32_25(LPITEMIDLIST iil1,LPITEMIDLIST iil2) {
640         DWORD           len1,len2;
641         LPITEMIDLIST    newiil;
642
643         len1    = SHELL32_152(iil1)-2;
644         len2    = SHELL32_152(iil2);
645         newiil  = SHELL32_196(len1+len2);
646         memcpy(newiil,iil1,len1);
647         memcpy(((char*)newiil)+len1,iil2,len2);
648         return newiil;
649 }
650
651 /*************************************************************************
652  *                       SHELL32_155                    [SHELL32.155]
653  * free_check_ptr - frees memory (if not NULL) allocated by SHMalloc allocator
654  */
655 DWORD WINAPI SHELL32_155(LPVOID x) {
656         if (!x)
657                 return 0;
658         return SHELL32_195(x);
659 }