Added a new debugging channel io to allow read/writes on a port to be
[wine] / dlls / shell32 / 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  *           1998 Jürgen Schmied
12  */
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <ctype.h>
17 #include "windows.h"
18 #include "winerror.h"
19 #include "file.h"
20 #include "shell.h"
21 #include "heap.h"
22 #include "module.h"
23 #include "neexe.h"
24 #include "resource.h"
25 #include "dlgs.h"
26 #include "win.h"
27 #include "graphics.h"
28 #include "cursoricon.h"
29 #include "interfaces.h"
30 #include "shlobj.h"
31 #include "debug.h"
32 #include "winreg.h"
33 #include "winnls.h"
34 #include "winversion.h"
35 #include "shell32_main.h"
36
37 /*************************************************************************
38  * SHChangeNotifyRegister [SHELL32.2]
39  * NOTES
40  *   Idlist is an array of structures and Count specifies how many items in the array
41  *   (usually just one I think).
42  */
43 DWORD WINAPI
44 SHChangeNotifyRegister(
45     HWND32 hwnd,
46     LONG events1,
47     LONG events2,
48     DWORD msg,
49     int count,
50     IDSTRUCT *idlist)
51 {       FIXME(shell,"(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):stub.\n",
52                 hwnd,events1,events2,msg,count,idlist);
53         return 0;
54 }
55 /*************************************************************************
56  * SHChangeNotifyDeregister [SHELL32.4]
57  */
58 DWORD WINAPI
59 SHChangeNotifyDeregister(LONG x1,LONG x2)
60 {       FIXME(shell,"(0x%08lx,0x%08lx):stub.\n",x1,x2);
61         return 0;
62 }
63
64 /*************************************************************************
65  * PathIsRoot [SHELL32.29]
66  */
67 BOOL32 WINAPI PathIsRoot32A(LPCSTR x)
68 {       TRACE(shell,"%s\n",x);
69         if (*(x+1)==':' && *(x+2)=='\\')                /* "X:\" */
70           return 1;
71         if (*x=='\\')           /* "\" */
72           return 0;
73         if (x[0]=='\\' && x[1]=='\\')           /* UNC "\\<xx>\" */
74         { int   foundbackslash = 0;
75           x=x+2;
76           while (*x)
77           { if (*x++=='\\')
78               foundbackslash++;
79           }
80           if (foundbackslash<=1)        /* max 1 \ more ... */
81             return 1;
82         }
83         return 0;
84 }
85 BOOL32 WINAPI PathIsRoot32W(LPCWSTR x) 
86 {       TRACE(shell,"%s\n",debugstr_w(x));
87         if (*(x+1)==':' && *(x+2)=='\\')                /* "X:\" */
88           return 1;
89         if (*x == (WCHAR) '\\')         /* "\" */
90           return 0;
91         if (x[0]==(WCHAR)'\\' && x[1]==(WCHAR)'\\')     /* UNC "\\<xx>\" */
92         { int   foundbackslash = 0;
93           x=x+2;
94           while (*x) 
95           { if (*x++==(WCHAR)'\\')
96               foundbackslash++;
97           }
98           if (foundbackslash<=1)        /* max 1 \ more ... */
99             return 1;
100         }
101         return 0;
102 }
103 BOOL32 WINAPI PathIsRoot32AW(LPCVOID x) 
104 {       if (VERSION_OsIsUnicode())
105           return PathIsRoot32W(x);
106         return PathIsRoot32A(x);
107
108 }
109 /*************************************************************************
110  * PathBuildRoot [SHELL32.30]
111  */
112 LPSTR WINAPI PathBuildRoot(LPSTR root,BYTE drive) {
113   TRACE(shell,"%p %i\n",root, drive);
114         strcpy(root,"A:\\");
115         root[0]+=drive;
116         return root;
117 }
118
119 /*************************************************************************
120  * PathFindExtension [SHELL32.31]
121  *
122  * NOTES
123  *     returns pointer to last . in last pathcomponent or at \0.
124  */
125 LPCSTR WINAPI PathFindExtension32A(LPCSTR path) 
126 {       LPCSTR   lastpoint = NULL;
127         TRACE(shell,"%p %s\n",path,path);
128         while (*path) 
129         { if (*path=='\\'||*path==' ')
130             lastpoint=NULL;
131           if (*path=='.')
132             lastpoint=path;
133           path++;
134         }
135         return lastpoint?lastpoint:path;
136 }
137 LPCWSTR WINAPI PathFindExtension32W(LPCWSTR path) 
138 {       LPCWSTR   lastpoint = NULL;
139         TRACE(shell,"%p L%s\n",path,debugstr_w(path));
140         while (*path)
141         { if (*path==(WCHAR)'\\'||*path==(WCHAR)' ')
142             lastpoint=NULL;
143           if (*path==(WCHAR)'.')
144             lastpoint=path;
145           path++;
146         }
147         return lastpoint?lastpoint:path;
148 }
149 LPCVOID WINAPI PathFindExtension32AW(LPCVOID path) 
150 {       if (VERSION_OsIsUnicode())
151           return PathFindExtension32W(path);
152         return PathFindExtension32A(path);
153
154 }
155
156 /*************************************************************************
157  * PathAddBackslash [SHELL32.32]
158  * 
159  * NOTES
160  *     append \ if there is none
161  */
162 LPSTR WINAPI PathAddBackslash32A(LPSTR path)
163 {       int len;
164         TRACE(shell,"%p->%s\n",path,path);
165
166         len = strlen(path);
167         if (len && path[len-1]!='\\') 
168         { path[len]  = '\\';
169           path[len+1]= 0x00;
170           return path+len+1;
171         }
172         return path+len;
173 }
174 LPWSTR WINAPI PathAddBackslash32W(LPWSTR path)
175 {       int len;
176         TRACE(shell,"%p->%s\n",path,debugstr_w(path));
177
178         len = lstrlen32W(path);
179         if (len && path[len-1]!=(WCHAR)'\\') 
180         { path[len]  = (WCHAR)'\\';
181           path[len+1]= 0x00;
182           return path+len+1;
183         }
184         return path+len;
185 }
186 LPVOID WINAPI PathAddBackslash32AW(LPVOID path)
187 {       if(VERSION_OsIsUnicode())
188           return PathAddBackslash32W(path);
189         return PathAddBackslash32A(path);
190 }
191
192 /*************************************************************************
193  * PathRemoveBlanks [SHELL32.33]
194  * 
195  * NOTES
196  *     remove spaces from beginning and end of passed string
197  */
198 LPSTR WINAPI PathRemoveBlanks(LPSTR str)
199 { LPSTR x = str;
200   TRACE(shell,"%s\n",str);
201   while (*x==' ') x++;
202   if (x!=str)
203           strcpy(str,x);
204   if (!*str)
205           return str;
206   x=str+strlen(str)-1;
207   while (*x==' ')
208           x--;
209   if (*x==' ')
210           *x='\0';
211   return x;
212 }
213
214
215 /*************************************************************************
216  * PathFindFilename [SHELL32.34]
217  * 
218  * NOTES
219  *     basename(char *fn);
220  */
221 LPVOID WINAPI PathFindFilename(LPVOID fn)
222 {       LPSTR aslash,aptr;
223         LPWSTR wslash,wptr;
224         
225         if(VERSION_OsIsUnicode())
226         { wslash = wptr = (LPWSTR) fn;
227           TRACE(shell,"L%s\n",debugstr_w(wslash));
228           while (wptr[0]) 
229           { if (((wptr[0]=='\\') || (wptr[0]==':')) && wptr[1] && wptr[1]!='\\')
230               wslash = wptr+1;
231             wptr++;
232           }
233           return (LPVOID) wslash;
234         }
235         aslash = aptr = (LPSTR) fn;
236         TRACE(shell,"%s\n",aslash);
237         while (aptr[0]) 
238         { if (((aptr[0]=='\\') || (aptr[0]==':')) && aptr[1] && aptr[1]!='\\')
239               aslash = aptr+1;
240             aptr++;
241         }
242         return (LPVOID) aslash;
243 }
244
245 /*************************************************************************
246  * PathRemoveFileSpec [SHELL32.35]
247  * 
248  * NOTES
249  *     bool getpath(char *pathname); truncates passed argument to a valid path
250  *     returns if the string was modified or not.
251  *     "\foo\xx\foo"-> "\foo\xx"
252  *     "\" -> "\"
253  *     "a:\foo" -> "a:\"
254  */
255 DWORD WINAPI PathRemoveFileSpec(LPSTR fn) {
256         LPSTR   x,cutplace;
257   TRACE(shell,"%s\n",fn);
258         if (!fn[0])
259                 return 0;
260         x=fn;
261         cutplace = fn;
262         while (*x) {
263                 if (*x=='\\') {
264                         cutplace=x++;
265                         continue;
266                 }
267                 if (*x==':') {
268                         x++;
269                         if (*x=='\\')
270                                 cutplace=++x;
271                         continue; /* already x++ed */
272                 }
273                 x++;
274         }
275         if (!*cutplace)
276                 return 0;
277         if (cutplace==fn) {
278                 if (fn[0]=='\\') {
279                         if (!fn[1])
280                                 return 0;
281                         fn[0]='\0';
282                         return 1;
283                 }
284         }
285         *cutplace='\0';
286         return 1;
287 }
288
289 /*************************************************************************
290  * PathAppend [SHELL32.36]
291  * 
292  * NOTES
293  *     concat_paths(char*target,const char*add);
294  *     concats "target\\add" and writes them to target
295  */
296 LPSTR WINAPI PathAppend(LPSTR x1,LPSTR x2) {
297   TRACE(shell,"%s %s\n",x1,x2);
298   while (x2[0]=='\\') x2++;
299   return PathCombine32A(x1,x1,x2);
300 }
301
302 /*************************************************************************
303  * PathCombine [SHELL32.37]
304  * 
305  * NOTES
306  *  if lpszFile='.' skip it
307  *  szDest can be equal to lpszFile. Thats why we use sTemp
308  */
309 LPSTR WINAPI PathCombine32A(LPSTR szDest, LPCSTR lpszDir, LPCSTR lpszFile) 
310 {       char sTemp[MAX_PATH];
311         TRACE(shell,"%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
312         
313         
314         if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) ) 
315         { strcpy(szDest,lpszDir);
316           return szDest;
317         }
318
319         /*  if lpszFile is a complete path don't care about lpszDir */
320         if (PathIsRoot32A(lpszFile))
321         { strcpy(szDest,lpszFile);
322         }
323         strcpy(sTemp,lpszDir);
324         PathAddBackslash32A(sTemp);
325         strcat(sTemp,lpszFile);
326         strcpy(szDest,sTemp);
327         return szDest;
328 }
329 LPWSTR WINAPI PathCombine32W(LPWSTR szDest, LPCWSTR lpszDir, LPCWSTR lpszFile) 
330 {       WCHAR sTemp[MAX_PATH];
331         TRACE(shell,"%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
332                          lpszFile, debugstr_w(lpszFile));
333         
334         
335         if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) ) 
336         { lstrcpy32W(szDest,lpszDir);
337           return szDest;
338         }
339
340         /*  if lpszFile is a complete path don't care about lpszDir */
341         if (PathIsRoot32W(lpszFile))
342         { lstrcpy32W(szDest,lpszFile);
343         }
344         lstrcpy32W(sTemp,lpszDir);
345         PathAddBackslash32W(sTemp);
346         lstrcat32W(sTemp,lpszFile);
347         lstrcpy32W(szDest,sTemp);
348         return szDest;
349 }
350 LPVOID WINAPI PathCombine32AW(LPVOID szDest, LPCVOID lpszDir, LPCVOID lpszFile) 
351 {       if (VERSION_OsIsUnicode())
352           return PathCombine32W( szDest, lpszDir, lpszFile );
353         return PathCombine32A( szDest, lpszDir, lpszFile );
354 }
355
356 /*************************************************************************
357  * PathIsUNC [SHELL32.39]
358  * 
359  * NOTES
360  *     PathIsUNC(char*path);
361  */
362 BOOL32 WINAPI PathIsUNC(LPCSTR path) {
363   TRACE(shell,"%s\n",path);
364         if ((path[0]=='\\') && (path[1]=='\\'))
365                 return TRUE;
366         return FALSE;
367 }
368 /*************************************************************************
369  *  PathIsExe [SHELL32.43]
370  * 
371  */
372 BOOL32 WINAPI PathIsExe (LPCSTR path)
373 {  TRACE(shell,"path=%s\n",path);
374     return FALSE;
375 }
376
377 /*************************************************************************
378  * PathFileExists [SHELL32.45]
379  * 
380  * NOTES
381  *     file_exists(char *fn);
382  */
383 BOOL32 WINAPI PathFileExists(LPSTR fn) {
384   TRACE(shell,"%s\n",fn);
385    if (GetFileAttributes32A(fn)==-1)
386         return FALSE;
387     else
388         return TRUE;
389 }
390 /*************************************************************************
391  * PathMatchSpec [SHELL32.46]
392  * 
393  * NOTES
394  *     used from COMDLG32
395  */
396
397 BOOL32 WINAPI PathMatchSpec(LPSTR x, LPSTR y) 
398 {       FIXME(shell,"%s %s stub\n",x,y);
399         return TRUE;
400 }
401
402 /*************************************************************************
403  * PathResolve [SHELL32.51]
404  */
405 DWORD WINAPI PathResolve(LPCSTR s,DWORD x2,DWORD x3) {
406         FIXME(shell,"(%s,0x%08lx,0x%08lx),stub!\n",s,x2,x3);
407         return 0;
408 }
409
410 /*************************************************************************
411  * PathGetArgs [SHELL32.52]
412  *
413  * NOTES
414  *     look for next arg in string. handle "quoted" strings
415  *     returns pointer to argument *AFTER* the space. Or to the \0.
416  */
417 LPVOID WINAPI PathGetArgs(LPVOID cmdline) 
418 {       BOOL32  qflag = FALSE;
419         LPWSTR wptr;
420         LPSTR aptr;
421         
422         if (VERSION_OsIsUnicode())
423         { TRACE(shell,"%sL\n",debugstr_w((LPWSTR)cmdline));
424           wptr=(LPWSTR) cmdline;
425           while (*wptr) 
426           { if ((*wptr==' ') && !qflag)
427                 return wptr+1;
428             if (*wptr=='"')
429                 qflag=!qflag;
430             wptr++;
431           }
432           return (LPVOID) wptr;
433         }
434         TRACE(shell,"%s\n",(LPSTR)cmdline);
435         aptr=(LPSTR) cmdline;
436         while (*aptr) 
437         { if ((*aptr==' ') && !qflag)
438             return aptr+1;
439           if (*aptr=='"')
440             qflag=!qflag;
441           aptr++;
442         }
443         return (LPVOID) aptr;
444 }
445
446 /*************************************************************************
447  * PathUnquoteSpaces [SHELL32.56]
448  * 
449  * NOTES
450  *     unquote string (remove ")
451  */
452 VOID WINAPI PathUnquoteSpaces(LPSTR str) {
453     DWORD      len = lstrlen32A(str);
454     TRACE(shell,"%s\n",str);
455     if (*str!='"') return;
456     if (str[len-1]!='"') return;
457     str[len-1]='\0';
458     lstrcpy32A(str,str+1);
459     return;
460 }
461
462 /*************************************************************************
463  * ParseField [SHELL32.58]
464  *
465  */
466 DWORD WINAPI ParseField(LPCSTR src,DWORD x2,LPSTR target,DWORD pathlen) {
467         FIXME(shell,"(%s,0x%08lx,%p,%ld):stub.\n",
468                 src,x2,target,pathlen
469         );
470         if (!src)
471                 return 0;
472         return 0;
473 }
474
475 /*************************************************************************
476  * PickIconDlg [SHELL32.62]
477  * 
478  */
479 DWORD WINAPI PickIconDlg(DWORD x,DWORD y,DWORD z,DWORD a) {
480         FIXME(shell,"(%08lx,%08lx,%08lx,%08lx):stub.\n",x,y,z,a);
481         return 0xffffffff;
482 }
483
484 /*************************************************************************
485  * GetFileNameFromBrowse [SHELL32.63]
486  * 
487  */
488 DWORD WINAPI GetFileNameFromBrowse(HWND32 howner, LPSTR targetbuf, DWORD len, DWORD x, LPCSTR suffix, LPCSTR y, LPCSTR cmd) {
489     FIXME(shell,"(%04x,%p,%ld,%08lx,%s,%s,%s):stub.\n",
490             howner,targetbuf,len,x,suffix,y,cmd
491     );
492     /* puts up a Open Dialog and requests input into targetbuf */
493     /* OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_FILEMUSTEXIST|OFN_unknown */
494     lstrcpy32A(targetbuf,"x:\\s3.exe");
495     return 1;
496 }
497
498 /*************************************************************************
499  * SHGetSettings [SHELL32.68]
500  * 
501  */
502 DWORD WINAPI SHGetSettings(DWORD x,DWORD y,DWORD z) {
503         FIXME(shell,"(0x%08lx,0x%08lx,0x%08lx):stub.\n",
504                 x,y,z
505         );
506         return 0;
507 }
508
509 /*************************************************************************
510  * Shell_GetCachedImageIndex [SHELL32.72]
511  *
512  */
513 void WINAPI Shell_GetCachedImageIndex(LPVOID x,DWORD y,DWORD z) 
514 {       if( VERSION_OsIsUnicode())
515         { FIXME(shell,"(L%s,%08lx,%08lx):stub.\n",debugstr_w((LPWSTR)x),y,z);
516         }
517         else
518         { FIXME(shell,"(%s,%08lx,%08lx):stub.\n",debugstr_a((LPSTR)x),y,z);
519         }
520 }
521
522 /*************************************************************************
523  * SHShellFolderView_Message [SHELL32.73]
524  *
525  * PARAMETERS
526  *  hwndCabinet defines the explorer cabinet window that contains the 
527  *              shellview you need to communicate with
528  *  uMsg        identifying the SFVM enum to perform
529  *  lParam
530  *
531  * NOTES
532  *  Message SFVM_REARRANGE = 1
533  *    This message gets sent when a column gets clicked to instruct the
534  *    shell view to re-sort the item list. lParam identifies the column
535  *    that was clicked.
536  */
537 int WINAPI SHShellFolderView_Message(HWND32 hwndCabinet,UINT32 uMsg,LPARAM lParam)
538 { FIXME(shell,"%04x %08ux %08lx stub\n",hwndCabinet,uMsg,lParam);
539   return 0;
540 }
541
542 /*************************************************************************
543  * PathYetAnotherMakeUniqueName [SHELL32.75]
544  * 
545  * NOTES
546  *     exported by ordinal
547  */
548 BOOL32 WINAPI PathYetAnotherMakeUniqueName(LPDWORD x,LPDWORD y) {
549     FIXME(shell,"(%p,%p):stub.\n",x,y);
550     return TRUE;
551 }
552
553 /*************************************************************************
554  * SHMapPIDLToSystemImageListIndex [SHELL32.77]
555  *
556  * PARAMETERS
557  * x  pointer to an instance of IShellFolder 
558  * 
559  * NOTES
560  *     exported by ordinal
561  *
562  */
563 DWORD WINAPI
564 SHMapPIDLToSystemImageListIndex(LPSHELLFOLDER sh,DWORD y,DWORD z)
565 { FIXME(shell,"(SF=%p,pidl=%08lx,%08lx):stub.\n",sh,y,z);
566   return 0;
567 }
568
569 /*************************************************************************
570  * OleStrToStrN  [SHELL32.78]
571  * 
572  * NOTES
573  *     exported by ordinal
574  * FIXME
575  *  wrong implemented OleStr is NOT wide string !!!! (jsch)
576  */
577 BOOL32 WINAPI
578 OleStrToStrN (LPSTR lpMulti, INT32 nMulti, LPCWSTR lpWide, INT32 nWide) {
579     return WideCharToMultiByte (0, 0, lpWide, nWide,
580         lpMulti, nMulti, NULL, NULL);
581 }
582
583 /*************************************************************************
584  * StrToOleStrN  [SHELL32.79]
585  *
586  * NOTES
587  *     exported by ordinal
588  * FIXME
589  *  wrong implemented OleStr is NOT wide string !!!! (jsch)
590 */
591 BOOL32 WINAPI
592 StrToOleStrN (LPWSTR lpWide, INT32 nWide, LPCSTR lpMulti, INT32 nMulti) {
593     return MultiByteToWideChar (0, 0, lpMulti, nMulti, lpWide, nWide);
594 }
595
596 /*************************************************************************
597  * SHCloneSpecialIDList [SHELL32.89]
598  * 
599  * PARAMETERS
600  *  hwndOwner   [in] 
601  *  nFolder     [in]    CSIDL_xxxxx ??
602  *
603  * RETURNS
604  *  pidl ??
605  * NOTES
606  *     exported by ordinal
607  */
608 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND32 hwndOwner,DWORD nFolder,DWORD x3)
609 {       LPITEMIDLIST ppidl;
610         WARN(shell,"(hwnd=0x%x,csidl=0x%lx,0x%lx):semi-stub.\n",
611                                          hwndOwner,nFolder,x3);
612
613         SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
614
615         return ppidl;
616 }
617
618 /*************************************************************************
619  * IsLFNDrive [SHELL32.119]
620  * 
621  * NOTES
622  *     exported by ordinal Name
623  */
624 BOOL32 WINAPI IsLFNDrive(LPCSTR path) {
625     DWORD       fnlen;
626
627     if (!GetVolumeInformation32A(path,NULL,0,NULL,&fnlen,NULL,NULL,0))
628         return FALSE;
629     return fnlen>12;
630 }
631
632 /*************************************************************************
633  * SHGetSpecialFolderPath [SHELL32.175]
634  * 
635  * NOTES
636  *     exported by ordinal
637  */
638 void WINAPI SHGetSpecialFolderPath(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
639     FIXME(shell,"(0x%04lx,0x%04lx,csidl=0x%04lx,0x%04lx):stub.\n",
640       x1,x2,x3,x4
641     );
642 }
643
644 /*************************************************************************
645  * RegisterShellHook [SHELL32.181]
646  *
647  * PARAMS
648  *      hwnd [I]  window handle
649  *      y    [I]  flag ????
650  * 
651  * NOTES
652  *     exported by ordinal
653  */
654 void WINAPI RegisterShellHook32(HWND32 hwnd, DWORD y) {
655     FIXME(shell,"(0x%08x,0x%08lx):stub.\n",hwnd,y);
656 }
657
658 /*************************************************************************
659  * ShellMessageBoxA [SHELL32.183]
660  *
661  * Format and output errormessage.
662  *
663  * NOTES
664  *     exported by ordinal
665  */
666 void __cdecl
667 ShellMessageBoxA(HMODULE32 hmod,HWND32 hwnd,DWORD id,DWORD x,DWORD type,LPVOID arglist) {
668         char    buf[100],buf2[100]/*,*buf3*/;
669 /*      LPVOID  args = &arglist;*/
670
671         if (!LoadString32A(hmod,x,buf,100))
672                 strcpy(buf,"Desktop");
673 //      LoadString32A(hmod,id,buf2,100);
674         /* FIXME: the varargs handling doesn't. */
675 //      FormatMessage32A(0x500,buf2,0,0,(LPSTR)&buf3,256,(LPDWORD)&args);
676
677         FIXME(shell,"(%08lx,%08lx,%08lx(%s),%08lx(%s),%08lx,%p):stub.\n",
678                 (DWORD)hmod,(DWORD)hwnd,id,buf2,x,buf,type,arglist
679         );
680         /*MessageBox32A(hwnd,buf3,buf,id|0x10000);*/
681 }
682
683 /*************************************************************************
684  * SHRestricted [SHELL32.100]
685  *
686  * walks through policy table, queries <app> key, <type> value, returns 
687  * queried (DWORD) value.
688  * {0x00001,Explorer,NoRun}
689  * {0x00002,Explorer,NoClose}
690  * {0x00004,Explorer,NoSaveSettings}
691  * {0x00008,Explorer,NoFileMenu}
692  * {0x00010,Explorer,NoSetFolders}
693  * {0x00020,Explorer,NoSetTaskbar}
694  * {0x00040,Explorer,NoDesktop}
695  * {0x00080,Explorer,NoFind}
696  * {0x00100,Explorer,NoDrives}
697  * {0x00200,Explorer,NoDriveAutoRun}
698  * {0x00400,Explorer,NoDriveTypeAutoRun}
699  * {0x00800,Explorer,NoNetHood}
700  * {0x01000,Explorer,NoStartBanner}
701  * {0x02000,Explorer,RestrictRun}
702  * {0x04000,Explorer,NoPrinterTabs}
703  * {0x08000,Explorer,NoDeletePrinter}
704  * {0x10000,Explorer,NoAddPrinter}
705  * {0x20000,Explorer,NoStartMenuSubFolders}
706  * {0x40000,Explorer,MyDocsOnNet}
707  * {0x80000,WinOldApp,NoRealMode}
708  *
709  * NOTES
710  *     exported by ordinal
711  */
712 DWORD WINAPI SHRestricted (DWORD pol) {
713         HKEY    xhkey;
714
715         FIXME(shell,"(%08lx):stub.\n",pol);
716         if (RegOpenKey32A(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Policies",&xhkey))
717                 return 0;
718         /* FIXME: do nothing for now, just return 0 (== "allowed") */
719         RegCloseKey(xhkey);
720         return 0;
721 }
722
723 /*************************************************************************
724  * PathGetExtension [SHELL32.158]
725  *
726  * NOTES
727  *     exported by ordinal
728  */
729 LPCSTR WINAPI PathGetExtension32A(LPCSTR path,DWORD y,DWORD z)
730 {       TRACE(shell,"(%s,%08lx,%08lx)\n",path,y,z);
731         path = PathFindExtension32A(path);
732         return *path?(path+1):path;
733 }
734 LPCWSTR WINAPI PathGetExtension32W(LPCWSTR path,DWORD y,DWORD z)
735 {       TRACE(shell,"(L%s,%08lx,%08lx)\n",debugstr_w(path),y,z);
736         path = PathFindExtension32W(path);
737         return *path?(path+1):path;
738 }
739 LPCVOID WINAPI PathGetExtension32AW(LPCVOID path,DWORD y,DWORD z) 
740 {       if (VERSION_OsIsUnicode())
741           return PathGetExtension32W(path,y,z);
742         return PathGetExtension32A(path,y,z);
743
744 }
745
746 /*************************************************************************
747  * SHCreateDirectory [SHELL32.165]
748  *
749  * NOTES
750  *  exported by ordinal
751  *  not sure about LPSECURITY_ATTRIBUTES
752  */
753 DWORD WINAPI SHCreateDirectory(LPSECURITY_ATTRIBUTES sec,LPCSTR path) {
754         TRACE(shell,"(%p,%s):stub.\n",sec,path);
755         if (CreateDirectory32A(path,sec))
756                 return TRUE;
757         /* SHChangeNotify(8,1,path,0); */
758         return FALSE;
759 #if 0
760         if (SHELL32_79(path,(LPVOID)x))
761                 return 0;
762         FIXME(shell,"(%08lx,%s):stub.\n",x,path);
763         return 0;
764 #endif
765 }
766
767 /*************************************************************************
768  * SHFree [SHELL32.195]
769  *
770  * NOTES
771  *     free_ptr() - frees memory using IMalloc
772  *     exported by ordinal
773  */
774 DWORD WINAPI SHFree(LPVOID x) {
775   TRACE(shell,"%p\n",x);
776   /*return LocalFree32((HANDLE32)x);*/ /* crashes */
777   return HeapFree(GetProcessHeap(),0,x);
778 }
779
780 /*************************************************************************
781  * SHAlloc [SHELL32.196]
782  *
783  * NOTES
784  *     void *task_alloc(DWORD len), uses SHMalloc allocator
785  *     exported by ordinal
786  */
787 LPVOID WINAPI SHAlloc(DWORD len) {
788  /* void * ret = (LPVOID)LocalAlloc32(len,LMEM_ZEROINIT);*/ /* chrashes */
789  void * ret = (LPVOID) HeapAlloc(GetProcessHeap(),0,len);
790   TRACE(shell,"%lu bytes at %p\n",len, ret);
791   return ret;
792 }
793
794 /*************************************************************************
795  * OpenRegStream [SHELL32.85]
796  *
797  * NOTES
798  *     exported by ordinal
799  */
800 DWORD WINAPI OpenRegStream(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
801     FIXME(shell,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx):stub.\n",
802         x1,x2,x3,x4
803     );
804     return 0;
805 }
806
807 /*************************************************************************
808  * SHRegisterDragDrop [SHELL32.86]
809  *
810  * NOTES
811  *     exported by ordinal
812  */
813 DWORD WINAPI SHRegisterDragDrop(HWND32 hwnd,DWORD x2) {
814     FIXME (shell, "(0x%08x,0x%08lx):stub.\n", hwnd, x2);
815     return 0;
816 }
817
818 /*************************************************************************
819  * SHRevokeDragDrop [SHELL32.87]
820  *
821  * NOTES
822  *     exported by ordinal
823  */
824 DWORD WINAPI SHRevokeDragDrop(DWORD x) {
825     FIXME(shell,"(0x%08lx):stub.\n",x);
826     return 0;
827 }
828
829 /*************************************************************************
830  * RunFileDlg [SHELL32.61]
831  *
832  * NOTES
833  *     Original name: RunFileDlg (exported by ordinal)
834  */
835 DWORD WINAPI
836 RunFileDlg (HWND32 hwndOwner, DWORD dwParam1, DWORD dwParam2,
837             LPSTR lpszTitle, LPSTR lpszPrompt, UINT32 uFlags)
838 {
839     FIXME (shell,"(0x%08x 0x%lx 0x%lx \"%s\" \"%s\" 0x%x):stub.\n",
840            hwndOwner, dwParam1, dwParam2, lpszTitle, lpszPrompt, uFlags);
841     return 0;
842 }
843
844 /*************************************************************************
845  * ExitWindowsDialog [SHELL32.60]
846  *
847  * NOTES
848  *     exported by ordinal
849  */
850 DWORD WINAPI
851 ExitWindowsDialog (HWND32 hwndOwner)
852 {
853     FIXME (shell,"(0x%08x):stub.\n", hwndOwner);
854     return 0;
855 }
856
857 /*************************************************************************
858  * ArrangeWindows [SHELL32.184]
859  * 
860  */
861 DWORD WINAPI
862 ArrangeWindows (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3,
863                 DWORD dwParam4, DWORD dwParam5)
864 {
865     FIXME (shell,"(0x%lx 0x%lx 0x%lx 0x%lx 0x%lx):stub.\n",
866            dwParam1, dwParam2, dwParam3, dwParam4, dwParam5);
867     return 0;
868 }
869
870 /*************************************************************************
871  * SHCLSIDFromString [SHELL32.147]
872  *
873  * NOTES
874  *     exported by ordinal
875  */
876 DWORD WINAPI
877 SHCLSIDFromString (DWORD dwParam1, DWORD dwParam2)
878 {
879     FIXME (shell,"(0x%lx 0x%lx):stub.\n", dwParam1, dwParam2);
880     FIXME (shell,"(\"%s\" \"%s\"):stub.\n", (LPSTR)dwParam1, (LPSTR)dwParam2);
881
882     return 0;
883 }
884
885
886 /*************************************************************************
887  * SignalFileOpen [SHELL32.103]
888  *
889  * NOTES
890  *     exported by ordinal
891  */
892 DWORD WINAPI
893 SignalFileOpen (DWORD dwParam1)
894 {
895     FIXME (shell,"(0x%08lx):stub.\n", dwParam1);
896
897     return 0;
898 }
899
900 /*************************************************************************
901  * SHAddToRecentDocs [SHELL32.234]
902  *
903  * PARAMETERS
904  *   uFlags  [IN] SHARD_PATH or SHARD_PIDL
905  *   pv      [IN] string or pidl, NULL clears the list
906  *
907  * NOTES
908  *     exported by name
909  */
910 DWORD WINAPI SHAddToRecentDocs32 (UINT32 uFlags,LPCVOID pv)   
911 { if (SHARD_PIDL==uFlags)
912   { FIXME (shell,"(0x%08x,pidl=%p):stub.\n", uFlags,pv);
913         }
914         else
915         { FIXME (shell,"(0x%08x,%s):stub.\n", uFlags,(char*)pv);
916         }
917   return 0;
918 }
919 /*************************************************************************
920  * SHFileOperation32 [SHELL32.242]
921  *
922  */
923 DWORD WINAPI SHFileOperation32(DWORD x)
924 {       FIXME(shell,"0x%08lx stub\n",x);
925         return 0;
926
927 }
928
929 /*************************************************************************
930  * SHFileOperation32A [SHELL32.243]
931  *
932  * NOTES
933  *     exported by name
934  */
935 DWORD WINAPI SHFileOperation32A (LPSHFILEOPSTRUCT32A lpFileOp)   
936 { FIXME (shell,"(%p):stub.\n", lpFileOp);
937   return 1;
938 }
939 /*************************************************************************
940  * SHFileOperation32W [SHELL32.244]
941  *
942  * NOTES
943  *     exported by name
944  */
945 DWORD WINAPI SHFileOperation32W (LPSHFILEOPSTRUCT32W lpFileOp)   
946 { FIXME (shell,"(%p):stub.\n", lpFileOp);
947   return 1;
948 }
949
950 /*************************************************************************
951  * SHChangeNotify [SHELL32.239]
952  *
953  * NOTES
954  *     exported by name
955  */
956 DWORD WINAPI SHChangeNotify32 (
957     INT32   wEventId,  /* [IN] flags that specifies the event*/
958     UINT32  uFlags,   /* [IN] the meaning of dwItem[1|2]*/
959                 LPCVOID dwItem1,
960                 LPCVOID dwItem2)
961 { FIXME (shell,"(0x%08x,0x%08ux,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);
962   return 0;
963 }
964 /*************************************************************************
965  * SHCreateShellFolderViewEx [SHELL32.174]
966  *
967  * NOTES
968  *  see IShellFolder::CreateViewObject
969  */
970 HRESULT WINAPI SHCreateShellFolderViewEx32(
971   LPSHELLVIEWDATA psvcbi, /*[in ] shelltemplate struct*/
972   LPVOID* ppv)            /*[out] IShellView pointer*/
973 { FIXME (shell,"(%p,%p):stub.\n", psvcbi,ppv);
974   return 0;
975 }
976 /*************************************************************************
977  * SHFind_InitMenuPopup [SHELL32.149]
978  *
979  * NOTES
980  *  Registers the menu behind the "Start" button
981  *
982  * PARAMETERS
983  *  hMenu               [in] handel of menu previously created
984  *  hWndParent  [in] parent window
985  *  w                   [in] no pointer
986  *  x                   [in] no pointer
987  */
988 HRESULT WINAPI SHFind_InitMenuPopup (HMENU32 hMenu, HWND32 hWndParent, DWORD w, DWORD x)
989 {       FIXME(shell,"hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
990                 hMenu,hWndParent,w,x);
991         return 0;
992 }
993 /*************************************************************************
994  * FileMenu_InitMenuPopup [SHELL32.109]
995  *
996  */
997 HRESULT WINAPI FileMenu_InitMenuPopup (DWORD hmenu)
998 {       FIXME(shell,"hmenu=0x%lx stub\n",hmenu);
999         return 0;
1000 }
1001 /*************************************************************************
1002  * FileMenu_Create [SHELL32.114]
1003  *
1004  * w retval from LoadBitmapA
1005  *
1006  *
1007  */
1008 HRESULT WINAPI FileMenu_Create (DWORD u, DWORD v, DWORD w, DWORD x, DWORD z)
1009 { FIXME(shell,"0x%08lx 0x%08lx hbmp=0x%lx 0x%08lx 0x%08lx stub\n",u,v,w,x,z);
1010   return 0;
1011 }
1012 /*************************************************************************
1013  * FileMenu_TrackPopupMenuEx [SHELL32.116]
1014  *
1015  * PARAMETERS
1016  *  uFlags              [in]    according to TrackPopupMenuEx
1017  *  posX                [in]
1018  *  posY                [in]
1019  *  hWndParent          [in]
1020  *  z   could be rect (trace) or TPMPARAMS (TrackPopupMenuEx)
1021  */
1022 HRESULT WINAPI FileMenu_TrackPopupMenuEx (DWORD t, DWORD uFlags, DWORD posX, DWORD posY, HWND32 hWndParent, DWORD z)
1023 {       FIXME(shell,"0x%lx flags=0x%lx posx=0x%lx posy=0x%lx hwndp=0x%x 0x%lx stub\n",
1024                 t,uFlags,posX,posY, hWndParent,z);
1025         return 0;
1026 }
1027 /*************************************************************************
1028  *  SHWinHelp [SHELL32.127]
1029  *
1030  */
1031 HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z)
1032 {       FIXME(shell,"0x%08lx 0x%08lx 0x%08lx 0x%08lx stub\n",v,w,x,z);
1033         return 0;
1034 }
1035 /*************************************************************************
1036  *  SHRunControlPanel [SHELL32.161]
1037  *
1038  */
1039 HRESULT WINAPI SHRunControlPanel (DWORD x, DWORD z)
1040 {       FIXME(shell,"0x%08lx 0x%08lx stub\n",x,z);
1041         return 0;
1042 }
1043 /*************************************************************************
1044  *  SHSimpleIDListFromPath [SHELL32.162]
1045  *
1046  */
1047 LPITEMIDLIST WINAPI SHSimpleIDListFromPath (LPCSTR lpszPath)
1048 {
1049         FIXME(shell,"(%s): stub\n",lpszPath);
1050         return 0;
1051 }
1052 /*************************************************************************
1053  * ShellExecuteEx [SHELL32.291]
1054  *
1055  */
1056 BOOL32 WINAPI ShellExecuteEx32A (LPSHELLEXECUTEINFO32A sei)
1057 {       CHAR szTemp[MAX_PATH];
1058
1059         FIXME(shell,"(%p): stub\n",sei);
1060
1061         if (sei->fMask & SEE_MASK_IDLIST)
1062         { SHGetPathFromIDList32A (sei->lpIDList,szTemp);
1063           TRACE (shell,"-- idlist=%p (%s)\n", sei->lpIDList, szTemp);
1064         }
1065
1066         if (sei->fMask & SEE_MASK_CLASSNAME)
1067         { TRACE (shell,"-- classname= %s\n", sei->lpClass);
1068         }
1069     
1070         if (sei->lpVerb)
1071         { TRACE (shell,"-- action=%s\n", sei->lpVerb);
1072         }
1073         
1074         return 0;
1075 }
1076 /*************************************************************************
1077  * SHSetInstanceExplorer [SHELL32.176]
1078  *
1079  */
1080 HRESULT WINAPI SHSetInstanceExplorer (DWORD u)
1081 {       FIXME(shell,"0x%08lx stub\n",u);
1082         return 0;
1083 }
1084 /*************************************************************************
1085  * SHGetInstanceExplorer [SHELL32.256]
1086  *
1087  * NOTES
1088  *  exported by name
1089  */
1090 HRESULT WINAPI SHGetInstanceExplorer (DWORD u)
1091 {       FIXME(shell,"0x%08lx stub\n",u);
1092         return 0;
1093 }
1094 /*************************************************************************
1095  * SHFreeUnusedLibraries [SHELL32.123]
1096  *
1097  * NOTES
1098  *  exported by name
1099  */
1100 HRESULT WINAPI SHFreeUnusedLibraries (DWORD u)
1101 {       FIXME(shell,"0x%08lx stub\n",u);
1102         return 0;
1103 }
1104 /*************************************************************************
1105  * DAD_ShowDragImage [SHELL32.137]
1106  *
1107  * NOTES
1108  *  exported by name
1109  */
1110 HRESULT WINAPI DAD_ShowDragImage (DWORD u)
1111 { FIXME(shell,"0x%08lx stub\n",u);
1112   return 0;
1113 }
1114 /*************************************************************************
1115  * FileMenu_Destroy [SHELL32.118]
1116  *
1117  * NOTES
1118  *  exported by name
1119  */
1120 HRESULT WINAPI FileMenu_Destroy (DWORD u)
1121 { FIXME(shell,"0x%08lx stub\n",u);
1122   return 0;
1123 }
1124 /*************************************************************************
1125  * SHGetDataFromIDListA [SHELL32.247]
1126  *
1127  */
1128 HRESULT WINAPI SHGetDataFromIDListA(DWORD u, DWORD v, DWORD w, DWORD x, DWORD y)
1129 {       FIXME(shell,"0x%04lx 0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n",u,v,w,x,y);
1130         return 0;
1131 }
1132 /*************************************************************************
1133  * SHRegCloseKey32 [NT4.0:SHELL32.505]
1134  *
1135  */
1136 HRESULT WINAPI SHRegCloseKey32 (HKEY hkey)
1137 {       TRACE(shell,"0x%04x\n",hkey);
1138         return RegCloseKey( hkey );
1139 }
1140 /*************************************************************************
1141  * SHRegOpenKey32A [SHELL32.506]
1142  *
1143  */
1144 HRESULT WINAPI SHRegOpenKey32A(HKEY hKey, LPSTR lpSubKey, LPHKEY phkResult)
1145 {       FIXME(shell,"(0x%08x, %s, %p)\n", hKey, debugstr_a(lpSubKey),
1146               phkResult);
1147         return RegOpenKey32A(hKey, lpSubKey, phkResult);
1148 }
1149
1150 /*************************************************************************
1151  * SHRegOpenKey32W [NT4.0:SHELL32.507]
1152  *
1153  */
1154 HRESULT WINAPI SHRegOpenKey32W (HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey)
1155 {       WARN(shell,"0x%04x %s %p\n",hkey,debugstr_w(lpszSubKey),retkey);
1156         return RegOpenKey32W( hkey, lpszSubKey, retkey );
1157 }
1158 /*************************************************************************
1159  * SHRegQueryValueExA [SHELL32.509]
1160  *
1161  */
1162 HRESULT WINAPI SHRegQueryValueEx32A(DWORD u, LPSTR v, DWORD w, DWORD x,
1163                                   DWORD y, DWORD z)
1164 {       FIXME(shell,"0x%04lx %s 0x%04lx 0x%04lx 0x%04lx  0x%04lx stub\n",
1165                 u,debugstr_a(v),w,x,y,z);
1166         return 0;
1167 }
1168 /*************************************************************************
1169  * SHRegQueryValue32W [NT4.0:SHELL32.510]
1170  *
1171  */
1172 HRESULT WINAPI SHRegQueryValue32W (HKEY hkey, LPWSTR lpszSubKey,
1173                                  LPWSTR lpszData, LPDWORD lpcbData )
1174 {       WARN(shell,"0x%04x %s %p %p semi-stub\n",
1175                 hkey, debugstr_w(lpszSubKey), lpszData, lpcbData);
1176         return RegQueryValue32W( hkey, lpszSubKey, lpszData, lpcbData );
1177 }
1178
1179 /*************************************************************************
1180  * SHRegQueryValueEx32W [NT4.0:SHELL32.511]
1181  *
1182  * FIXME 
1183  *  if the datatype REG_EXPAND_SZ then expand the string and change
1184  *  *pdwType to REG_SZ. 
1185  */
1186 HRESULT WINAPI SHRegQueryValueEx32W (HKEY hkey, LPWSTR pszValue, LPDWORD pdwReserved,
1187                  LPDWORD pdwType, LPVOID pvData, LPDWORD pcbData)
1188 {       DWORD ret;
1189         WARN(shell,"0x%04x %s %p %p %p %p semi-stub\n",
1190                 hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
1191         ret = RegQueryValueEx32W ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
1192         return ret;
1193 }
1194
1195 /*************************************************************************
1196  * ReadCabinetState [NT 4.0:SHELL32.651]
1197  *
1198  */
1199 HRESULT WINAPI ReadCabinetState(DWORD u, DWORD v)
1200 {       FIXME(shell,"0x%04lx 0x%04lx stub\n",u,v);
1201         return 0;
1202 }
1203 /*************************************************************************
1204  * WriteCabinetState [NT 4.0:SHELL32.652]
1205  *
1206  */
1207 HRESULT WINAPI WriteCabinetState(DWORD u)
1208 {       FIXME(shell,"0x%04lx stub\n",u);
1209         return 0;
1210 }
1211 /*************************************************************************
1212  * FileIconInit [SHELL32.660]
1213  *
1214  */
1215 BOOL32 WINAPI FileIconInit(BOOL32 bFullInit)
1216 {       FIXME(shell,"(%s)\n", bFullInit ? "true" : "false");
1217         return 0;
1218 }
1219 /*************************************************************************
1220  * IsUserAdmin [NT 4.0:SHELL32.680]
1221  *
1222  */
1223 HRESULT WINAPI IsUserAdmin()
1224 {       FIXME(shell,"stub\n");
1225         return TRUE;
1226 }
1227 /*************************************************************************
1228  * StrRetToStrN [SHELL32.96]
1229  * 
1230  * converts a STRRET to a normal string
1231  *
1232  * NOTES
1233  *  FIXME the string handling is to simple (different STRRET choices)
1234  *  at the moment only CSTR
1235  *  the pidl is for STRRET OFFSET
1236  */
1237 HRESULT WINAPI StrRetToStrN (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
1238 {       TRACE(shell,"dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
1239
1240         switch (src->uType)
1241         { case STRRET_WSTR:
1242             WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
1243             SHFree(src->u.pOleStr);
1244             break;
1245
1246           case STRRET_CSTRA:
1247             if (VERSION_OsIsUnicode())
1248               lstrcpynAtoW((LPWSTR)dest, src->u.cStr, len);
1249             else
1250               strncpy((LPSTR)dest, src->u.cStr, len);
1251             break;
1252
1253           case STRRET_OFFSETA:
1254             if (pidl)
1255             { if(VERSION_OsIsUnicode())
1256                 lstrcpynAtoW((LPWSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
1257               else
1258                 strncpy((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
1259               break;
1260             }
1261
1262           default:
1263             FIXME(shell,"unknown type!\n");
1264             if (len)
1265             { *(LPSTR)dest = '\0';
1266             }
1267             return(FALSE);
1268         }
1269         return(TRUE);
1270 }
1271
1272 /*************************************************************************
1273  * StrChrW [NT 4.0:SHELL32.651]
1274  *
1275  */
1276 LPWSTR WINAPI StrChrW (LPWSTR str, WCHAR x )
1277 {       LPWSTR ptr=str;
1278         
1279         TRACE(shell,"%s 0x%04x\n",debugstr_w(str),x);
1280         do 
1281         {  if (*ptr==x)
1282            { return ptr;
1283            }
1284            ptr++;
1285         } while (*ptr);
1286         return NULL;
1287 }
1288
1289 /*************************************************************************
1290  *      StrCmpNIW               [NT 4.0:SHELL32.*]
1291  *
1292  */
1293 INT32 WINAPI StrCmpNIW ( LPWSTR wstr1, LPWSTR wstr2, INT32 len)
1294 {       FIXME( shell,"%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
1295         return 0;
1296 }
1297
1298 /*************************************************************************
1299  * SHAllocShared [SHELL32.520]
1300  *
1301  * NOTES
1302  *  parameter1 is return value from HeapAlloc
1303  *  parameter2 is equal to the size allocated with HeapAlloc
1304  *  parameter3 is return value from GetCurrentProcessId
1305  *
1306  *  the return value is posted as lParam with 0x402 (WM_USER+2) to somewhere
1307  *  WM_USER+2 could be the undocumented CWM_SETPATH
1308  *  the allocated memory contains a pidl
1309  */
1310 HGLOBAL32 WINAPI SHAllocShared(LPVOID psrc, DWORD size, DWORD procID)
1311 {       HGLOBAL32 hmem;
1312         LPVOID pmem;
1313         
1314         TRACE(shell,"ptr=%p size=0x%04lx procID=0x%04lx\n",psrc,size,procID);
1315         hmem = GlobalAlloc32(GMEM_FIXED, size);
1316         if (!hmem)
1317           return 0;
1318         
1319         pmem =  GlobalLock32 (hmem);
1320
1321         if (! pmem)
1322           return 0;
1323           
1324         memcpy (pmem, psrc, size);
1325         GlobalUnlock32(hmem); 
1326         return hmem;
1327 }
1328 /*************************************************************************
1329  * SHLockShared [SHELL32.521]
1330  *
1331  * NOTES
1332  *  parameter1 is return value from SHAllocShared
1333  *  parameter2 is return value from GetCurrentProcessId
1334  *  the receiver of (WM_USER+2) trys to lock the HANDLE (?) 
1335  *  the returnvalue seems to be a memoryadress
1336  */
1337 void * WINAPI SHLockShared(HANDLE32 hmem, DWORD procID)
1338 {       TRACE(shell,"handle=0x%04x procID=0x%04lx\n",hmem,procID);
1339         return GlobalLock32(hmem);
1340 }
1341 /*************************************************************************
1342  * SHUnlockShared [SHELL32.522]
1343  *
1344  * NOTES
1345  *  parameter1 is return value from SHLockShared
1346  */
1347 BOOL32 WINAPI SHUnlockShared(HANDLE32 pmem)
1348 {       TRACE(shell,"handle=0x%04x\n",pmem);
1349         return GlobalUnlock32(pmem); 
1350 }
1351 /*************************************************************************
1352  * SHFreeShared [SHELL32.523]
1353  *
1354  * NOTES
1355  *  parameter1 is return value from SHAllocShared
1356  *  parameter2 is return value from GetCurrentProcessId
1357  */
1358 HANDLE32 WINAPI SHFreeShared(HANDLE32 hmem, DWORD procID)
1359 {       TRACE(shell,"handle=0x%04x 0x%04lx\n",hmem,procID);
1360         return GlobalFree32(hmem);
1361 }
1362
1363 /*************************************************************************
1364  * SetAppStartingCursor32 [SHELL32.99]
1365  *
1366  */
1367 HRESULT WINAPI SetAppStartingCursor32(DWORD u, DWORD v)
1368 {       FIXME(shell,"0x%04lx 0x%04lx stub\n",u,v );
1369         return 0;
1370 }
1371 /*************************************************************************
1372  * SHLoadOLE32 [SHELL32.151]
1373  *
1374  */
1375 HRESULT WINAPI SHLoadOLE32(DWORD u)
1376 {       FIXME(shell,"0x%04lx stub\n",u);
1377         return S_OK;
1378 }
1379 /*************************************************************************
1380  * Shell_MergeMenus32 [SHELL32.67]
1381  *
1382  */
1383 BOOL32 _SHIsMenuSeparator(HMENU32 hm, int i)
1384 {
1385         MENUITEMINFO32A mii;
1386
1387         mii.cbSize = sizeof(MENUITEMINFO32A);
1388         mii.fMask = MIIM_TYPE;
1389         mii.cch = 0;    /* WARNING: We MUST initialize it to 0*/
1390         if (!GetMenuItemInfo32A(hm, i, TRUE, &mii))
1391         { return(FALSE);
1392         }
1393
1394         if (mii.fType & MFT_SEPARATOR)
1395         { return(TRUE);
1396         }
1397
1398         return(FALSE);
1399 }
1400 #define MM_ADDSEPARATOR         0x00000001L
1401 #define MM_SUBMENUSHAVEIDS      0x00000002L
1402 HRESULT WINAPI Shell_MergeMenus32 (HMENU32 hmDst, HMENU32 hmSrc, UINT32 uInsert, UINT32 uIDAdjust, UINT32 uIDAdjustMax, ULONG uFlags)
1403 {       int             nItem;
1404         HMENU32         hmSubMenu;
1405         BOOL32          bAlreadySeparated;
1406         MENUITEMINFO32A miiSrc;
1407         char            szName[256];
1408         UINT32          uTemp, uIDMax = uIDAdjust;
1409
1410         FIXME(shell,"hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x  0x%04lx stub\n",
1411                  hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
1412
1413         if (!hmDst || !hmSrc)
1414         { return uIDMax;
1415         }
1416
1417         nItem = GetMenuItemCount32(hmDst);
1418         if (uInsert >= (UINT32)nItem)
1419         { uInsert = (UINT32)nItem;
1420           bAlreadySeparated = TRUE;
1421         }
1422         else
1423         { bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
1424         }
1425         if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
1426         { /* Add a separator between the menus */
1427           InsertMenu32A(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
1428           bAlreadySeparated = TRUE;
1429         }
1430
1431
1432         /* Go through the menu items and clone them*/
1433         for (nItem = GetMenuItemCount32(hmSrc) - 1; nItem >= 0; nItem--)
1434         { miiSrc.cbSize = sizeof(MENUITEMINFO32A);
1435           miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
1436           /* We need to reset this every time through the loop in case
1437           menus DON'T have IDs*/
1438           miiSrc.fType = MFT_STRING;
1439           miiSrc.dwTypeData = szName;
1440           miiSrc.dwItemData = 0;
1441           miiSrc.cch = sizeof(szName);
1442
1443           if (!GetMenuItemInfo32A(hmSrc, nItem, TRUE, &miiSrc))
1444           { continue;
1445           }
1446           if (miiSrc.fType & MFT_SEPARATOR)
1447           { /* This is a separator; don't put two of them in a row*/
1448             if (bAlreadySeparated)
1449             { continue;
1450             }
1451             bAlreadySeparated = TRUE;
1452           }
1453           else if (miiSrc.hSubMenu)
1454           { if (uFlags & MM_SUBMENUSHAVEIDS)
1455             { /* Adjust the ID and check it*/
1456               miiSrc.wID += uIDAdjust;
1457               if (miiSrc.wID > uIDAdjustMax)
1458               { continue;
1459               }
1460               if (uIDMax <= miiSrc.wID)
1461               { uIDMax = miiSrc.wID + 1;
1462               }
1463             }
1464             else
1465             { /* Don't set IDs for submenus that didn't have them already */
1466               miiSrc.fMask &= ~MIIM_ID;
1467             }
1468             hmSubMenu = miiSrc.hSubMenu;
1469             miiSrc.hSubMenu = CreatePopupMenu32();
1470             if (!miiSrc.hSubMenu)
1471             { return(uIDMax);
1472             }
1473             uTemp = Shell_MergeMenus32(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags&MM_SUBMENUSHAVEIDS);
1474             if (uIDMax <= uTemp)
1475             { uIDMax = uTemp;
1476             }
1477             bAlreadySeparated = FALSE;
1478           }
1479           else
1480           { /* Adjust the ID and check it*/
1481             miiSrc.wID += uIDAdjust;
1482             if (miiSrc.wID > uIDAdjustMax)
1483             { continue;
1484             }
1485             if (uIDMax <= miiSrc.wID)
1486             { uIDMax = miiSrc.wID + 1;
1487             }
1488             bAlreadySeparated = FALSE;
1489           }
1490           if (!InsertMenuItem32A(hmDst, uInsert, TRUE, &miiSrc))
1491           { return(uIDMax);
1492           }
1493         }
1494
1495         /* Ensure the correct number of separators at the beginning of the
1496         inserted menu items*/
1497         if (uInsert == 0)
1498         { if (bAlreadySeparated)
1499           { DeleteMenu32(hmDst, uInsert, MF_BYPOSITION);
1500           }
1501         }
1502         else
1503         { if (_SHIsMenuSeparator(hmDst, uInsert-1))
1504           { if (bAlreadySeparated)
1505             { DeleteMenu32(hmDst, uInsert, MF_BYPOSITION);
1506             }
1507           }
1508           else
1509           { if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
1510             { /* Add a separator between the menus*/
1511               InsertMenu32A(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
1512             }
1513           }
1514         }
1515         return(uIDMax);
1516
1517 }
1518 /*************************************************************************
1519  * PathGetDriveNumber32 [SHELL32.57]
1520  *
1521  */
1522 HRESULT WINAPI PathGetDriveNumber32(LPSTR u)
1523 {       FIXME(shell,"%s stub\n",debugstr_a(u));
1524         return 0;
1525 }
1526 /*************************************************************************
1527  * DriveType32 [SHELL32.64]
1528  *
1529  */
1530 HRESULT WINAPI DriveType32(DWORD u)
1531 {       FIXME(shell,"0x%04lx stub\n",u);
1532         return 0;
1533 }
1534 /*************************************************************************
1535  * SHAbortInvokeCommand [SHELL32.198]
1536  *
1537  */
1538 HRESULT WINAPI SHAbortInvokeCommand()
1539 {       FIXME(shell,"stub\n");
1540         return 1;
1541 }
1542 /*************************************************************************
1543  * SHOutOfMemoryMessageBox [SHELL32.126]
1544  *
1545  */
1546 HRESULT WINAPI SHOutOfMemoryMessageBox(DWORD u, DWORD v, DWORD w)
1547 {       FIXME(shell,"0x%04lx 0x%04lx 0x%04lx stub\n",u,v,w);
1548         return 0;
1549 }
1550 /*************************************************************************
1551  * SHFlushClipboard [SHELL32.121]
1552  *
1553  */
1554 HRESULT WINAPI SHFlushClipboard()
1555 {       FIXME(shell,"stub\n");
1556         return 1;
1557 }
1558 /*************************************************************************
1559  * SheGetDirW [SHELL32.281]
1560  *
1561  */
1562 HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v)
1563 {       FIXME(shell,"%s %s stub\n",debugstr_w(u),debugstr_w(v) );
1564         return 0;
1565 }
1566 /*************************************************************************
1567  * StrRChrW [SHELL32.320]
1568  *
1569  */
1570 LPWSTR WINAPI StrRChrW(LPWSTR lpStart, LPWSTR lpEnd, DWORD wMatch)
1571 {       LPWSTR wptr=NULL;
1572         TRACE(shell,"%s %s 0x%04x\n",debugstr_w(lpStart),debugstr_w(lpEnd), (WCHAR)wMatch );
1573
1574         /* if the end not given, search*/
1575         if (!lpEnd)
1576         { lpEnd=lpStart;
1577           while (*lpEnd) 
1578             lpEnd++;
1579         }
1580
1581         do 
1582         { if (*lpStart==(WCHAR)wMatch)
1583             wptr = lpStart;
1584           lpStart++;  
1585         } while ( lpStart<=lpEnd ); 
1586         return wptr;
1587 }