- Better implementation for GetTopindex/GetOrigin/SetIconSpacing.
[wine] / dlls / shell32 / shellord.c
1 /*
2  * The parameters of many functions changes between different OS versions
3  * (NT uses Unicode strings, 95 uses ASCII strings)
4  *
5  * Copyright 1997 Marcus Meissner
6  *           1998 Jürgen Schmied
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 #include "config.h"
23
24 #include <string.h>
25 #include <stdio.h>
26 #include "winerror.h"
27 #include "winreg.h"
28 #include "wine/debug.h"
29 #include "winnls.h"
30 #include "heap.h"
31
32 #include "wine/obj_base.h"
33 #include "shellapi.h"
34 #include "shlguid.h"
35 #include "shlobj.h"
36 #include "shell32_main.h"
37 #include "undocshell.h"
38 #include "pidl.h"
39 #include "shlwapi.h"
40 #include "commdlg.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(shell);
43 WINE_DECLARE_DEBUG_CHANNEL(pidl);
44
45 /* FIXME: !!! move CREATEMRULIST and flags to header file !!! */
46 /*        !!! it is in both here and comctl32undoc.c      !!! */
47 typedef struct tagCREATEMRULIST
48 {
49     DWORD  cbSize;        /* size of struct */
50     DWORD  nMaxItems;     /* max no. of items in list */
51     DWORD  dwFlags;       /* see below */
52     HKEY   hKey;          /* root reg. key under which list is saved */
53     LPCSTR lpszSubKey;    /* reg. subkey */
54     PROC   lpfnCompare;   /* item compare proc */
55 } CREATEMRULISTA, *LPCREATEMRULISTA;
56
57 /* dwFlags */
58 #define MRUF_STRING_LIST  0 /* list will contain strings */
59 #define MRUF_BINARY_LIST  1 /* list will contain binary data */
60 #define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
61
62 extern HANDLE WINAPI CreateMRUListA(LPCREATEMRULISTA lpcml);
63 extern DWORD  WINAPI FreeMRUList(HANDLE hMRUList);
64 extern INT    WINAPI AddMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData);
65 extern INT    WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum);
66 extern INT    WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize);
67
68 /*************************************************************************
69  * ParseFieldA                                  [internal]
70  *
71  * copies a field from a ',' delimited string
72  *
73  * first field is nField = 1
74  */
75 DWORD WINAPI ParseFieldA(
76         LPCSTR src,
77         DWORD nField,
78         LPSTR dst,
79         DWORD len)
80 {
81         WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n",debugstr_a(src),nField,dst,len);
82
83         if (!src || !src[0] || !dst || !len)
84           return 0;
85
86         /* skip n fields delimited by ',' */
87         while (nField > 1)
88         {
89           if (*src=='\0') return FALSE;
90           if (*(src++)==',') nField--;
91         }
92
93         /* copy part till the next ',' to dst */
94         while ( *src!='\0' && *src!=',' && (len--)>0 ) *(dst++)=*(src++);
95
96         /* finalize the string */
97         *dst=0x0;
98
99         return TRUE;
100 }
101
102 /*************************************************************************
103  * ParseFieldW                  [internal]
104  *
105  * copies a field from a ',' delimited string
106  *
107  * first field is nField = 1
108  */
109 DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len)
110 {
111         FIXME("(%s,0x%08lx,%p,%ld) stub\n",
112           debugstr_w(src), nField, dst, len);
113         return FALSE;
114 }
115
116 /*************************************************************************
117  * ParseField                   [SHELL32.58]
118  */
119 DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len)
120 {
121         if (SHELL_OsIsUnicode())
122           return ParseFieldW(src, nField, dst, len);
123         return ParseFieldA(src, nField, dst, len);
124 }
125
126 /*************************************************************************
127  * GetFileNameFromBrowse                        [SHELL32.63]
128  *
129  */
130 BOOL WINAPI GetFileNameFromBrowse(
131         HWND hwndOwner,
132         LPSTR lpstrFile,
133         DWORD nMaxFile,
134         LPCSTR lpstrInitialDir,
135         LPCSTR lpstrDefExt,
136         LPCSTR lpstrFilter,
137         LPCSTR lpstrTitle)
138 {
139     HMODULE hmodule;
140     FARPROC pGetOpenFileNameA;
141     OPENFILENAMEA ofn;
142     BOOL ret;
143
144     TRACE("%04x, %s, %ld, %s, %s, %s, %s)\n",
145           hwndOwner, lpstrFile, nMaxFile, lpstrInitialDir, lpstrDefExt,
146           lpstrFilter, lpstrTitle);
147
148     hmodule = LoadLibraryA("comdlg32.dll");
149     if(!hmodule) return FALSE;
150     pGetOpenFileNameA = GetProcAddress(hmodule, "GetOpenFileNameA");
151     if(!pGetOpenFileNameA)
152     {
153         FreeLibrary(hmodule);
154         return FALSE;
155     }
156
157     memset(&ofn, 0, sizeof(ofn));
158
159     ofn.lStructSize = sizeof(ofn);
160     ofn.hwndOwner = hwndOwner;
161     ofn.lpstrFilter = lpstrFilter;
162     ofn.lpstrFile = lpstrFile;
163     ofn.nMaxFile = nMaxFile;
164     ofn.lpstrInitialDir = lpstrInitialDir;
165     ofn.lpstrTitle = lpstrTitle;
166     ofn.lpstrDefExt = lpstrDefExt;
167     ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
168     ret = pGetOpenFileNameA(&ofn);
169
170     FreeLibrary(hmodule);
171     return ret;
172 }
173
174 /*************************************************************************
175  * SHGetSetSettings                             [SHELL32.68]
176  */
177 VOID WINAPI SHGetSetSettings(DWORD x, DWORD y, DWORD z)
178 {
179         FIXME("0x%08lx 0x%08lx 0x%08lx\n", x, y, z);
180 }
181
182 /*************************************************************************
183  * SHGetSettings                                [SHELL32.@]
184  *
185  * NOTES
186  *  the registry path are for win98 (tested)
187  *  and possibly are the same in nt40
188  *
189  */
190 VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask)
191 {
192         HKEY    hKey;
193         DWORD   dwData;
194         DWORD   dwDataSize = sizeof (DWORD);
195
196         TRACE("(%p 0x%08lx)\n",lpsfs,dwMask);
197
198         if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
199                                  0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
200           return;
201
202         if ( (SSF_SHOWEXTENSIONS & dwMask) && !RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
203           lpsfs->fShowExtensions  = ((dwData == 0) ?  0 : 1);
204
205         if ( (SSF_SHOWINFOTIP & dwMask) && !RegQueryValueExA(hKey, "ShowInfoTip", 0, 0, (LPBYTE)&dwData, &dwDataSize))
206           lpsfs->fShowInfoTip  = ((dwData == 0) ?  0 : 1);
207
208         if ( (SSF_DONTPRETTYPATH & dwMask) && !RegQueryValueExA(hKey, "DontPrettyPath", 0, 0, (LPBYTE)&dwData, &dwDataSize))
209           lpsfs->fDontPrettyPath  = ((dwData == 0) ?  0 : 1);
210
211         if ( (SSF_HIDEICONS & dwMask) && !RegQueryValueExA(hKey, "HideIcons", 0, 0, (LPBYTE)&dwData, &dwDataSize))
212           lpsfs->fHideIcons  = ((dwData == 0) ?  0 : 1);
213
214         if ( (SSF_MAPNETDRVBUTTON & dwMask) && !RegQueryValueExA(hKey, "MapNetDrvBtn", 0, 0, (LPBYTE)&dwData, &dwDataSize))
215           lpsfs->fMapNetDrvBtn  = ((dwData == 0) ?  0 : 1);
216
217         if ( (SSF_SHOWATTRIBCOL & dwMask) && !RegQueryValueExA(hKey, "ShowAttribCol", 0, 0, (LPBYTE)&dwData, &dwDataSize))
218           lpsfs->fShowAttribCol  = ((dwData == 0) ?  0 : 1);
219
220         if (((SSF_SHOWALLOBJECTS | SSF_SHOWSYSFILES) & dwMask) && !RegQueryValueExA(hKey, "Hidden", 0, 0, (LPBYTE)&dwData, &dwDataSize))
221         { if (dwData == 0)
222           { if (SSF_SHOWALLOBJECTS & dwMask)    lpsfs->fShowAllObjects  = 0;
223             if (SSF_SHOWSYSFILES & dwMask)      lpsfs->fShowSysFiles  = 0;
224           }
225           else if (dwData == 1)
226           { if (SSF_SHOWALLOBJECTS & dwMask)    lpsfs->fShowAllObjects  = 1;
227             if (SSF_SHOWSYSFILES & dwMask)      lpsfs->fShowSysFiles  = 0;
228           }
229           else if (dwData == 2)
230           { if (SSF_SHOWALLOBJECTS & dwMask)    lpsfs->fShowAllObjects  = 0;
231             if (SSF_SHOWSYSFILES & dwMask)      lpsfs->fShowSysFiles  = 1;
232           }
233         }
234         RegCloseKey (hKey);
235
236         TRACE("-- 0x%04x\n", *(WORD*)lpsfs);
237 }
238
239 /*************************************************************************
240  * SHShellFolderView_Message                    [SHELL32.73]
241  *
242  * PARAMETERS
243  *  hwndCabinet defines the explorer cabinet window that contains the
244  *              shellview you need to communicate with
245  *  uMsg        identifying the SFVM enum to perform
246  *  lParam
247  *
248  * NOTES
249  *  Message SFVM_REARRANGE = 1
250  *    This message gets sent when a column gets clicked to instruct the
251  *    shell view to re-sort the item list. lParam identifies the column
252  *    that was clicked.
253  */
254 int WINAPI SHShellFolderView_Message(
255         HWND hwndCabinet,
256         DWORD dwMessage,
257         DWORD dwParam)
258 {
259         FIXME("%04x %08lx %08lx stub\n",hwndCabinet, dwMessage, dwParam);
260         return 0;
261 }
262
263 /*************************************************************************
264  * RegisterShellHook                            [SHELL32.181]
265  *
266  * PARAMS
267  *      hwnd [I]  window handle
268  *      y    [I]  flag ????
269  *
270  * NOTES
271  *     exported by ordinal
272  */
273 BOOL WINAPI RegisterShellHook(
274         HWND hWnd,
275         DWORD dwType)
276 {
277         FIXME("(0x%08x,0x%08lx):stub.\n",hWnd, dwType);
278         return TRUE;
279 }
280 /*************************************************************************
281  * ShellMessageBoxW                             [SHELL32.182]
282  *
283  * Format and output errormessage.
284  *
285  * idText       resource ID of title or LPSTR
286  * idTitle      resource ID of title or LPSTR
287  *
288  * NOTES
289  *     exported by ordinal
290  */
291 int WINAPIV ShellMessageBoxW(
292         HINSTANCE hInstance,
293         HWND hWnd,
294         LPCWSTR lpText,
295         LPCWSTR lpCaption,
296         UINT uType,
297         ...)
298 {
299         WCHAR   szText[100],szTitle[100];
300         LPCWSTR pszText = szText, pszTitle = szTitle, pszTemp;
301         va_list args;
302         int     ret;
303
304         va_start(args, uType);
305         /* wvsprintfA(buf,fmt, args); */
306
307         TRACE("(%08lx,%08lx,%p,%p,%08x)\n",
308         (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType);
309
310         if (!HIWORD(lpCaption))
311           LoadStringW(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
312         else
313           pszTitle = lpCaption;
314
315         if (!HIWORD(lpText))
316           LoadStringW(hInstance, (DWORD)lpText, szText, sizeof(szText)/sizeof(szText[0]));
317         else
318           pszText = lpText;
319
320         FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
321                        pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
322
323         va_end(args);
324
325         ret = MessageBoxW(hWnd,pszTemp,pszTitle,uType);
326         LocalFree((HLOCAL)pszTemp);
327         return ret;
328 }
329
330 /*************************************************************************
331  * ShellMessageBoxA                             [SHELL32.183]
332  */
333 int WINAPIV ShellMessageBoxA(
334         HINSTANCE hInstance,
335         HWND hWnd,
336         LPCSTR lpText,
337         LPCSTR lpCaption,
338         UINT uType,
339         ...)
340 {
341         char    szText[100],szTitle[100];
342         LPCSTR  pszText = szText, pszTitle = szTitle, pszTemp;
343         va_list args;
344         int     ret;
345
346         va_start(args, uType);
347         /* wvsprintfA(buf,fmt, args); */
348
349         TRACE("(%08lx,%08lx,%p,%p,%08x)\n",
350         (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType);
351
352         if (!HIWORD(lpCaption))
353           LoadStringA(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle));
354         else
355           pszTitle = lpCaption;
356
357         if (!HIWORD(lpText))
358           LoadStringA(hInstance, (DWORD)lpText, szText, sizeof(szText));
359         else
360           pszText = lpText;
361
362         FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
363                        pszText, 0, 0, (LPSTR)&pszTemp, 0, &args);
364
365         va_end(args);
366
367         ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType);
368         LocalFree((HLOCAL)pszTemp);
369         return ret;
370 }
371
372 /*************************************************************************
373  * SHRegisterDragDrop                           [SHELL32.86]
374  *
375  * NOTES
376  *     exported by ordinal
377  */
378 HRESULT WINAPI SHRegisterDragDrop(
379         HWND hWnd,
380         LPDROPTARGET pDropTarget)
381 {
382         FIXME("(0x%08x,%p):stub.\n", hWnd, pDropTarget);
383         if (GetShellOle()) return pRegisterDragDrop(hWnd, pDropTarget);
384         return 0;
385 }
386
387 /*************************************************************************
388  * SHRevokeDragDrop                             [SHELL32.87]
389  *
390  * NOTES
391  *     exported by ordinal
392  */
393 HRESULT WINAPI SHRevokeDragDrop(HWND hWnd)
394 {
395     FIXME("(0x%08x):stub.\n",hWnd);
396     return 0;
397 }
398
399 /*************************************************************************
400  * SHDoDragDrop                                 [SHELL32.88]
401  *
402  * NOTES
403  *     exported by ordinal
404  */
405 HRESULT WINAPI SHDoDragDrop(
406         HWND hWnd,
407         LPDATAOBJECT lpDataObject,
408         LPDROPSOURCE lpDropSource,
409         DWORD dwOKEffect,
410         LPDWORD pdwEffect)
411 {
412     FIXME("(0x%04x %p %p 0x%08lx %p):stub.\n",
413     hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect);
414     return 0;
415 }
416
417 /*************************************************************************
418  * ArrangeWindows                               [SHELL32.184]
419  *
420  */
421 WORD WINAPI ArrangeWindows(
422         HWND hwndParent,
423         DWORD dwReserved,
424         LPCRECT lpRect,
425         WORD cKids,
426         CONST HWND * lpKids)
427 {
428     FIXME("(0x%08x 0x%08lx %p 0x%04x %p):stub.\n",
429            hwndParent, dwReserved, lpRect, cKids, lpKids);
430     return 0;
431 }
432
433 /*************************************************************************
434  * SignalFileOpen                               [SHELL32.103]
435  *
436  * NOTES
437  *     exported by ordinal
438  */
439 DWORD WINAPI
440 SignalFileOpen (DWORD dwParam1)
441 {
442     FIXME("(0x%08lx):stub.\n", dwParam1);
443
444     return 0;
445 }
446
447 /*************************************************************************
448  * SHADD_get_policy - helper function for SHAddToRecentDocs
449  *
450  * PARAMETERS
451  *   policy    [IN]  policy name (null termed string) to find
452  *   type      [OUT] ptr to DWORD to receive type
453  *   buffer    [OUT] ptr to area to hold data retrieved
454  *   len       [IN/OUT] ptr to DWORD holding size of buffer and getting
455  *                      length filled
456  *
457  * RETURNS
458  *   result of the SHQueryValueEx call
459  */
460 static INT SHADD_get_policy(LPSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len)
461 {
462     HKEY Policy_basekey;
463     INT ret;
464
465     /* Get the key for the policies location in the registry
466      */
467     if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
468                       "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
469                       0, KEY_READ, &Policy_basekey)) {
470
471         if (RegOpenKeyExA(HKEY_CURRENT_USER,
472                           "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
473                           0, KEY_READ, &Policy_basekey)) {
474             TRACE("No Explorer Policies location exists. Policy wanted=%s\n",
475                   policy);
476             *len = 0;
477             return ERROR_FILE_NOT_FOUND;
478         }
479     }
480
481     /* Retrieve the data if it exists
482      */
483     ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len);
484     RegCloseKey(Policy_basekey);
485     return ret;
486 }
487
488
489 /*************************************************************************
490  * SHADD_compare_mru - helper function for SHAddToRecentDocs
491  *
492  * PARAMETERS
493  *   data1     [IN] data being looked for
494  *   data2     [IN] data in MRU
495  *   cbdata    [IN] length from FindMRUData call (not used)
496  *
497  * RETURNS
498  *   position within MRU list that data was added.
499  */
500 static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData)
501 {
502     return lstrcmpiA(data1, data2);
503 }
504
505 /*************************************************************************
506  * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs
507  *
508  * PARAMETERS
509  *   mruhandle    [IN] handle for created MRU list
510  *   doc_name     [IN] null termed pure doc name
511  *   new_lnk_name [IN] null termed path and file name for .lnk file
512  *   buffer       [IN/OUT] 2048 byte area to consturct MRU data
513  *   len          [OUT] ptr to int to receive space used in buffer
514  *
515  * RETURNS
516  *   position within MRU list that data was added.
517  */
518 static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPSTR doc_name, LPSTR new_lnk_name,
519                                      LPSTR buffer, INT *len)
520 {
521     LPSTR ptr;
522     INT wlen;
523
524     /*FIXME: Document:
525      *  RecentDocs MRU data structure seems to be:
526      *    +0h   document file name w/ terminating 0h
527      *    +nh   short int w/ size of remaining
528      *    +n+2h 02h 30h, or 01h 30h, or 00h 30h  -  unknown
529      *    +n+4h 10 bytes zeros  -   unknown
530      *    +n+eh shortcut file name w/ terminating 0h
531      *    +n+e+nh 3 zero bytes  -  unknown
532      */
533
534     /* Create the MRU data structure for "RecentDocs"
535          */
536     ptr = buffer;
537     lstrcpyA(ptr, doc_name);
538     ptr += (lstrlenA(buffer) + 1);
539     wlen= lstrlenA(new_lnk_name) + 1 + 12;
540     *((short int*)ptr) = wlen;
541     ptr += 2;   /* step past the length */
542     *(ptr++) = 0x30;  /* unknown reason */
543     *(ptr++) = 0;     /* unknown, but can be 0x00, 0x01, 0x02 */
544     memset(ptr, 0, 10);
545     ptr += 10;
546     lstrcpyA(ptr, new_lnk_name);
547     ptr += (lstrlenA(new_lnk_name) + 1);
548     memset(ptr, 0, 3);
549     ptr += 3;
550     *len = ptr - buffer;
551
552     /* Add the new entry into the MRU list
553      */
554     return AddMRUData(mruhandle, (LPCVOID)buffer, *len);
555 }
556
557 /*************************************************************************
558  * SHAddToRecentDocs                            [SHELL32.@]
559  *
560  * PARAMETERS
561  *   uFlags  [IN] SHARD_PATH or SHARD_PIDL
562  *   pv      [IN] string or pidl, NULL clears the list
563  *
564  * NOTES
565  *     exported by name
566  *
567  * FIXME: ?? MSDN shows this as a VOID
568  */
569 DWORD WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
570 {
571 /* If list is a string list lpfnCompare has the following prototype
572  * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
573  * for binary lists the prototype is
574  * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
575  * where cbData is the no. of bytes to compare.
576  * Need to check what return value means identical - 0?
577  */
578
579
580     UINT olderrormode;
581     HKEY HCUbasekey;
582     CHAR doc_name[MAX_PATH];
583     CHAR link_dir[MAX_PATH];
584     CHAR new_lnk_filepath[MAX_PATH];
585     CHAR new_lnk_name[MAX_PATH];
586     IMalloc *ppM;
587     LPITEMIDLIST pidl;
588     HWND hwnd = 0;       /* FIXME:  get real window handle */
589     INT ret;
590     DWORD data[64], datalen, type;
591
592     /*FIXME: Document:
593      *  RecentDocs MRU data structure seems to be:
594      *    +0h   document file name w/ terminating 0h
595      *    +nh   short int w/ size of remaining
596      *    +n+2h 02h 30h, or 01h 30h, or 00h 30h  -  unknown
597      *    +n+4h 10 bytes zeros  -   unknown
598      *    +n+eh shortcut file name w/ terminating 0h
599      *    +n+e+nh 3 zero bytes  -  unknown
600      */
601
602     /* See if we need to do anything.
603      */
604     datalen = 64;
605     ret=SHADD_get_policy( "NoRecentDocsHistory", &type, &data, &datalen);
606     if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) {
607         ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret);
608         return 0;
609     }
610     if (ret == ERROR_SUCCESS) {
611         if (!( (type == REG_DWORD) ||
612                ((type == REG_BINARY) && (datalen == 4)) )) {
613             ERR("Error policy data for \"NoRecentDocsHistory\" not formated correctly, type=%ld, len=%ld\n",
614                 type, datalen);
615             return 0;
616         }
617
618         TRACE("policy value for NoRecentDocsHistory = %08lx\n", data[0]);
619         /* now test the actual policy value */
620         if ( data[0] != 0)
621             return 0;
622     }
623
624     /* Open key to where the necessary info is
625      */
626     /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH)
627      *        and the close should be done during the _DETACH. The resulting
628      *        key is stored in the DLL global data.
629      */
630     if (RegCreateKeyExA(HKEY_CURRENT_USER,
631                         "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
632                         0, 0, 0, KEY_READ, 0, &HCUbasekey, 0)) {
633         ERR("Failed to create 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'\n");
634         return 0;
635     }
636
637     /* Get path to user's "Recent" directory
638      */
639     if(SUCCEEDED(SHGetMalloc(&ppM))) {
640         if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT,
641                                                  &pidl))) {
642             SHGetPathFromIDListA(pidl, link_dir);
643             IMalloc_Free(ppM, pidl);
644         }
645         else {
646             /* serious issues */
647             link_dir[0] = 0;
648             ERR("serious issues 1\n");
649         }
650         IMalloc_Release(ppM);
651     }
652     else {
653         /* serious issues */
654         link_dir[0] = 0;
655         ERR("serious issues 2\n");
656     }
657     TRACE("Users Recent dir %s\n", link_dir);
658
659     /* If no input, then go clear the lists */
660     if (!pv) {
661         /* clear user's Recent dir
662          */
663
664         /* FIXME: delete all files in "link_dir"
665          *
666          * while( more files ) {
667          *    lstrcpyA(old_lnk_name, link_dir);
668          *    PathAppendA(old_lnk_name, filenam);
669          *    DeleteFileA(old_lnk_name);
670          * }
671          */
672         FIXME("should delete all files in %s\\ \n", link_dir);
673
674         /* clear MRU list
675          */
676         /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against
677          *  HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer
678          *  and naturally it fails w/ rc=2. It should do it against
679          *  HKEY_CURRENT_USER which is where it is stored, and where
680          *  the MRU routines expect it!!!!
681          */
682         RegDeleteKeyA(HCUbasekey, "RecentDocs");
683         RegCloseKey(HCUbasekey);
684         return 0;
685     }
686
687     /* Have data to add, the jobs to be done:
688      *   1. Add document to MRU list in registry "HKCU\Software\
689      *      Microsoft\Windows\CurrentVersion\Explorer\RecentDocs".
690      *   2. Add shortcut to document in the user's Recent directory
691      *      (CSIDL_RECENT).
692      *   3. Add shortcut to Start menu's Documents submenu.
693      */
694
695     /* Get the pure document name from the input
696      */
697     if (uFlags & SHARD_PIDL) {
698         SHGetPathFromIDListA((LPCITEMIDLIST) pv, doc_name);
699     }
700     else {
701         lstrcpyA(doc_name, (LPSTR) pv);
702     }
703     TRACE("full document name %s\n", doc_name);
704     PathStripPathA(doc_name);
705     TRACE("stripped document name %s\n", doc_name);
706
707
708     /* ***  JOB 1: Update registry for ...\Explorer\RecentDocs list  *** */
709
710     {  /* on input needs:
711         *      doc_name    -  pure file-spec, no path
712         *      link_dir    -  path to the user's Recent directory
713         *      HCUbasekey  -  key of ...Windows\CurrentVersion\Explorer" node
714         * creates:
715         *      new_lnk_name-  pure file-spec, no path for new .lnk file
716         *      new_lnk_filepath
717         *                  -  path and file name of new .lnk file
718         */
719         CREATEMRULISTA mymru;
720         HANDLE mruhandle;
721         INT len, pos, bufused, err;
722         INT i;
723         DWORD attr;
724         CHAR buffer[2048];
725         CHAR *ptr;
726         CHAR old_lnk_name[MAX_PATH];
727         short int slen;
728
729         mymru.cbSize = sizeof(CREATEMRULISTA);
730         mymru.nMaxItems = 15;
731         mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE;
732         mymru.hKey = HCUbasekey;
733         mymru.lpszSubKey = "RecentDocs";
734         mymru.lpfnCompare = &SHADD_compare_mru;
735         mruhandle = CreateMRUListA(&mymru);
736         if (!mruhandle) {
737             /* MRU failed */
738             ERR("MRU processing failed, handle zero\n");
739             RegCloseKey(HCUbasekey);
740             return 0;
741         }
742         len = lstrlenA(doc_name);
743         pos = FindMRUData(mruhandle, doc_name, len, 0);
744
745         /* Now get the MRU entry that will be replaced
746          * and delete the .lnk file for it
747          */
748         if ((bufused = EnumMRUListA(mruhandle, (pos == -1) ? 14 : pos,
749                                     buffer, 2048)) != -1) {
750             ptr = buffer;
751             ptr += (lstrlenA(buffer) + 1);
752             slen = *((short int*)ptr);
753             ptr += 2;  /* skip the length area */
754             if (bufused >= slen + (ptr-buffer)) {
755                 /* buffer size looks good */
756                 ptr += 12; /* get to string */
757                 len = bufused - (ptr-buffer);  /* get length of buf remaining */
758                 if ((lstrlenA(ptr) > 0) && (lstrlenA(ptr) <= len-1)) {
759                     /* appears to be good string */
760                     lstrcpyA(old_lnk_name, link_dir);
761                     PathAppendA(old_lnk_name, ptr);
762                     if (!DeleteFileA(old_lnk_name)) {
763                         if ((attr = GetFileAttributesA(old_lnk_name)) == -1) {
764                             if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) {
765                                 ERR("Delete for %s failed, err=%d, attr=%08lx\n",
766                                     old_lnk_name, err, attr);
767                             }
768                             else {
769                                 TRACE("old .lnk file %s did not exist\n",
770                                       old_lnk_name);
771                             }
772                         }
773                         else {
774                             ERR("Delete for %s failed, attr=%08lx\n",
775                                 old_lnk_name, attr);
776                         }
777                     }
778                     else {
779                         TRACE("deleted old .lnk file %s\n", old_lnk_name);
780                     }
781                 }
782             }
783         }
784
785         /* Create usable .lnk file name for the "Recent" directory
786          */
787         wsprintfA(new_lnk_name, "%s.lnk", doc_name);
788         lstrcpyA(new_lnk_filepath, link_dir);
789         PathAppendA(new_lnk_filepath, new_lnk_name);
790         i = 1;
791         olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS);
792         while (GetFileAttributesA(new_lnk_filepath) != -1) {
793             i++;
794             wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i);
795             lstrcpyA(new_lnk_filepath, link_dir);
796             PathAppendA(new_lnk_filepath, new_lnk_name);
797         }
798         SetErrorMode(olderrormode);
799         TRACE("new shortcut will be %s\n", new_lnk_filepath);
800
801         /* Now add the new MRU entry and data
802          */
803         pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name,
804                                         buffer, &len);
805         FreeMRUList(mruhandle);
806         TRACE("Updated MRU list, new doc is position %d\n", pos);
807     }
808
809     /* ***  JOB 2: Create shortcut in user's "Recent" directory  *** */
810
811     {  /* on input needs:
812         *      doc_name    -  pure file-spec, no path
813         *      new_lnk_filepath
814         *                  -  path and file name of new .lnk file
815         *      uFlags[in]  -  flags on call to SHAddToRecentDocs
816         *      pv[in]      -  document path/pidl on call to SHAddToRecentDocs
817         */
818         IShellLinkA *psl = NULL;
819         IPersistFile *pPf = NULL;
820         HRESULT hres;
821         CHAR desc[MAX_PATH];
822         WCHAR widelink[MAX_PATH];
823
824         CoInitialize(0);
825
826         hres = CoCreateInstance( &CLSID_ShellLink,
827                                  NULL,
828                                  CLSCTX_INPROC_SERVER,
829                                  &IID_IShellLinkA,
830                                  (LPVOID )&psl);
831         if(SUCCEEDED(hres)) {
832
833             hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile,
834                                              (LPVOID *)&pPf);
835             if(FAILED(hres)) {
836                 /* bombed */
837                 ERR("failed QueryInterface for IPersistFile %08lx\n", hres);
838                 goto fail;
839             }
840
841             /* Set the document path or pidl */
842             if (uFlags & SHARD_PIDL) {
843                 hres = IShellLinkA_SetIDList(psl, (LPCITEMIDLIST) pv);
844             } else {
845                 hres = IShellLinkA_SetPath(psl, (LPCSTR) pv);
846             }
847             if(FAILED(hres)) {
848                 /* bombed */
849                 ERR("failed Set{IDList|Path} %08lx\n", hres);
850                 goto fail;
851             }
852
853             lstrcpyA(desc, "Shortcut to ");
854             lstrcatA(desc, doc_name);
855             hres = IShellLinkA_SetDescription(psl, desc);
856             if(FAILED(hres)) {
857                 /* bombed */
858                 ERR("failed SetDescription %08lx\n", hres);
859                 goto fail;
860             }
861
862             MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1,
863                                 widelink, MAX_PATH);
864             /* create the short cut */
865             hres = IPersistFile_Save(pPf, widelink, TRUE);
866             if(FAILED(hres)) {
867                 /* bombed */
868                 ERR("failed IPersistFile::Save %08lx\n", hres);
869                 IPersistFile_Release(pPf);
870                 IShellLinkA_Release(psl);
871                 goto fail;
872             }
873             hres = IPersistFile_SaveCompleted(pPf, widelink);
874             IPersistFile_Release(pPf);
875             IShellLinkA_Release(psl);
876             TRACE("shortcut %s has been created, result=%08lx\n",
877                   new_lnk_filepath, hres);
878         }
879         else {
880             ERR("CoCreateInstance failed, hres=%08lx\n", hres);
881         }
882     }
883
884  fail:
885     CoUninitialize();
886
887     /* all done */
888     RegCloseKey(HCUbasekey);
889     return 0;
890 }
891
892 /*************************************************************************
893  * SHCreateShellFolderViewEx                    [SHELL32.174]
894  *
895  * NOTES
896  *  see IShellFolder::CreateViewObject
897  */
898 HRESULT WINAPI SHCreateShellFolderViewEx(
899         LPCSHELLFOLDERVIEWINFO psvcbi, /* [in] shelltemplate struct */
900         LPSHELLVIEW* ppv)              /* [out] IShellView pointer */
901 {
902         IShellView * psf;
903         HRESULT hRes;
904
905         TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=0x%08lx\n",
906           psvcbi->pshf, psvcbi->pidlFolder, psvcbi->lpfnCallback,
907           psvcbi->uViewMode, psvcbi->dwUser);
908
909         psf = IShellView_Constructor(psvcbi->pshf);
910
911         if (!psf)
912           return E_OUTOFMEMORY;
913
914         IShellView_AddRef(psf);
915         hRes = IShellView_QueryInterface(psf, &IID_IShellView, (LPVOID *)ppv);
916         IShellView_Release(psf);
917
918         return hRes;
919 }
920 /*************************************************************************
921  *  SHWinHelp                                   [SHELL32.127]
922  *
923  */
924 HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z)
925 {       FIXME("0x%08lx 0x%08lx 0x%08lx 0x%08lx stub\n",v,w,x,z);
926         return 0;
927 }
928 /*************************************************************************
929  *  SHRunControlPanel [SHELL32.161]
930  *
931  */
932 HRESULT WINAPI SHRunControlPanel (DWORD x, DWORD z)
933 {       FIXME("0x%08lx 0x%08lx stub\n",x,z);
934         return 0;
935 }
936
937 static LPUNKNOWN SHELL32_IExplorerInterface=0;
938 /*************************************************************************
939  * SHSetInstanceExplorer                        [SHELL32.176]
940  *
941  * NOTES
942  *  Sets the interface
943  */
944 HRESULT WINAPI SHSetInstanceExplorer (LPUNKNOWN lpUnknown)
945 {       TRACE("%p\n", lpUnknown);
946         SHELL32_IExplorerInterface = lpUnknown;
947         return (HRESULT) lpUnknown;
948 }
949 /*************************************************************************
950  * SHGetInstanceExplorer                        [SHELL32.@]
951  *
952  * NOTES
953  *  gets the interface pointer of the explorer and a reference
954  */
955 HRESULT WINAPI SHGetInstanceExplorer (LPUNKNOWN * lpUnknown)
956 {       TRACE("%p\n", lpUnknown);
957
958         *lpUnknown = SHELL32_IExplorerInterface;
959
960         if (!SHELL32_IExplorerInterface)
961           return E_FAIL;
962
963         IUnknown_AddRef(SHELL32_IExplorerInterface);
964         return NOERROR;
965 }
966 /*************************************************************************
967  * SHFreeUnusedLibraries                        [SHELL32.123]
968  *
969  * NOTES
970  *  exported by name
971  */
972 void WINAPI SHFreeUnusedLibraries (void)
973 {
974         FIXME("stub\n");
975 }
976 /*************************************************************************
977  * DAD_AutoScroll                               [SHELL32.129]
978  *
979  */
980 DWORD WINAPI DAD_AutoScroll(HWND hwnd, LPSCROLLSAMPLES samples, LPPOINT pt)
981 {
982     FIXME("hwnd = %04x %p %p\n",hwnd,samples,pt);
983     return 0;
984 }
985 /*************************************************************************
986  * DAD_DragEnter                                [SHELL32.130]
987  *
988  */
989 BOOL WINAPI DAD_DragEnter(HWND hwnd)
990 {
991     FIXME("hwnd = %04x\n",hwnd);
992     return FALSE;
993 }
994 /*************************************************************************
995  * DAD_DragEnterEx                              [SHELL32.131]
996  *
997  */
998 BOOL WINAPI DAD_DragEnterEx(HWND hwnd, POINT p)
999 {
1000     FIXME("hwnd = %04x (%ld,%ld)\n",hwnd,p.x,p.y);
1001     return FALSE;
1002 }
1003 /*************************************************************************
1004  * DAD_DragMove                         [SHELL32.134]
1005  *
1006  */
1007 BOOL WINAPI DAD_DragMove(POINT p)
1008 {
1009     FIXME("(%ld,%ld)\n",p.x,p.y);
1010     return FALSE;
1011 }
1012 /*************************************************************************
1013  * DAD_DragLeave                                [SHELL32.132]
1014  *
1015  */
1016 BOOL WINAPI DAD_DragLeave(VOID)
1017 {
1018     FIXME("\n");
1019     return FALSE;
1020 }
1021 /*************************************************************************
1022  * DAD_SetDragImage                             [SHELL32.136]
1023  *
1024  * NOTES
1025  *  exported by name
1026  */
1027 BOOL WINAPI DAD_SetDragImage(
1028         HIMAGELIST himlTrack,
1029         LPPOINT lppt)
1030 {
1031         FIXME("%p %p stub\n",himlTrack, lppt);
1032   return 0;
1033 }
1034 /*************************************************************************
1035  * DAD_ShowDragImage                            [SHELL32.137]
1036  *
1037  * NOTES
1038  *  exported by name
1039  */
1040 BOOL WINAPI DAD_ShowDragImage(BOOL bShow)
1041 {
1042         FIXME("0x%08x stub\n",bShow);
1043         return 0;
1044 }
1045 /*************************************************************************
1046  * ReadCabinetState                             [SHELL32.651] NT 4.0
1047  *
1048  */
1049 HRESULT WINAPI ReadCabinetState(DWORD u, DWORD v)
1050 {       FIXME("0x%04lx 0x%04lx stub\n",u,v);
1051         return 0;
1052 }
1053 /*************************************************************************
1054  * WriteCabinetState                            [SHELL32.652] NT 4.0
1055  *
1056  */
1057 HRESULT WINAPI WriteCabinetState(DWORD u)
1058 {       FIXME("0x%04lx stub\n",u);
1059         return 0;
1060 }
1061 /*************************************************************************
1062  * FileIconInit                                 [SHELL32.660]
1063  *
1064  */
1065 BOOL WINAPI FileIconInit(BOOL bFullInit)
1066 {       FIXME("(%s)\n", bFullInit ? "true" : "false");
1067         return 0;
1068 }
1069 /*************************************************************************
1070  * IsUserAdmin                                  [SHELL32.680] NT 4.0
1071  *
1072  */
1073 HRESULT WINAPI IsUserAdmin(void)
1074 {       FIXME("stub\n");
1075         return TRUE;
1076 }
1077
1078 /*************************************************************************
1079  * SHAllocShared                                [SHELL32.520]
1080  *
1081  * NOTES
1082  *  parameter1 is return value from HeapAlloc
1083  *  parameter2 is equal to the size allocated with HeapAlloc
1084  *  parameter3 is return value from GetCurrentProcessId
1085  *
1086  *  the return value is posted as lParam with 0x402 (WM_USER+2) to somewhere
1087  *  WM_USER+2 could be the undocumented CWM_SETPATH
1088  *  the allocated memory contains a pidl
1089  */
1090 HGLOBAL WINAPI SHAllocShared(LPVOID psrc, DWORD size, DWORD procID)
1091 {       HGLOBAL hmem;
1092         LPVOID pmem;
1093
1094         TRACE("ptr=%p size=0x%04lx procID=0x%04lx\n",psrc,size,procID);
1095         hmem = GlobalAlloc(GMEM_FIXED, size);
1096         if (!hmem)
1097           return 0;
1098
1099         pmem =  GlobalLock (hmem);
1100
1101         if (! pmem)
1102           return 0;
1103
1104         memcpy (pmem, psrc, size);
1105         GlobalUnlock(hmem);
1106         return hmem;
1107 }
1108 /*************************************************************************
1109  * SHLockShared                                 [SHELL32.521]
1110  *
1111  * NOTES
1112  *  parameter1 is return value from SHAllocShared
1113  *  parameter2 is return value from GetCurrentProcessId
1114  *  the receiver of (WM_USER+2) tries to lock the HANDLE (?)
1115  *  the return value seems to be a memory address
1116  */
1117 LPVOID WINAPI SHLockShared(HANDLE hmem, DWORD procID)
1118 {       TRACE("handle=0x%04x procID=0x%04lx\n",hmem,procID);
1119         return GlobalLock(hmem);
1120 }
1121 /*************************************************************************
1122  * SHUnlockShared                               [SHELL32.522]
1123  *
1124  * NOTES
1125  *  parameter1 is return value from SHLockShared
1126  */
1127 BOOL WINAPI SHUnlockShared(LPVOID pv)
1128 {
1129         TRACE("%p\n",pv);
1130         return GlobalUnlock((HANDLE)pv);
1131 }
1132 /*************************************************************************
1133  * SHFreeShared                                 [SHELL32.523]
1134  *
1135  * NOTES
1136  *  parameter1 is return value from SHAllocShared
1137  *  parameter2 is return value from GetCurrentProcessId
1138  */
1139 BOOL WINAPI SHFreeShared(
1140         HANDLE hMem,
1141         DWORD pid)
1142 {
1143         TRACE("handle=0x%04x 0x%04lx\n",hMem,pid);
1144         return GlobalFree(hMem);
1145 }
1146
1147 /*************************************************************************
1148  * SetAppStartingCursor                         [SHELL32.99]
1149  */
1150 HRESULT WINAPI SetAppStartingCursor(HWND u, DWORD v)
1151 {       FIXME("hwnd=0x%04x 0x%04lx stub\n",u,v );
1152         return 0;
1153 }
1154 /*************************************************************************
1155  * SHLoadOLE                                    [SHELL32.151]
1156  *
1157  */
1158 HRESULT WINAPI SHLoadOLE(DWORD u)
1159 {       FIXME("0x%04lx stub\n",u);
1160         return S_OK;
1161 }
1162 /*************************************************************************
1163  * DriveType                                    [SHELL32.64]
1164  *
1165  */
1166 HRESULT WINAPI DriveType(DWORD u)
1167 {       FIXME("0x%04lx stub\n",u);
1168         return 0;
1169 }
1170 /*************************************************************************
1171  * SHAbortInvokeCommand                         [SHELL32.198]
1172  *
1173  */
1174 HRESULT WINAPI SHAbortInvokeCommand(void)
1175 {       FIXME("stub\n");
1176         return 1;
1177 }
1178 /*************************************************************************
1179  * SHOutOfMemoryMessageBox                      [SHELL32.126]
1180  *
1181  */
1182 int WINAPI SHOutOfMemoryMessageBox(
1183         HWND hwndOwner,
1184         LPCSTR lpCaption,
1185         UINT uType)
1186 {
1187         FIXME("0x%04x %s 0x%08x stub\n",hwndOwner, lpCaption, uType);
1188         return 0;
1189 }
1190 /*************************************************************************
1191  * SHFlushClipboard                             [SHELL32.121]
1192  *
1193  */
1194 HRESULT WINAPI SHFlushClipboard(void)
1195 {       FIXME("stub\n");
1196         return 1;
1197 }
1198
1199 /*************************************************************************
1200  * SHWaitForFileToOpen                          [SHELL32.97]
1201  *
1202  */
1203 BOOL WINAPI SHWaitForFileToOpen(
1204         LPCITEMIDLIST pidl,
1205         DWORD dwFlags,
1206         DWORD dwTimeout)
1207 {
1208         FIXME("%p 0x%08lx 0x%08lx stub\n", pidl, dwFlags, dwTimeout);
1209         return 0;
1210 }
1211
1212 /************************************************************************
1213  *      @                               [SHELL32.654]
1214  *
1215  * NOTES: first parameter seems to be a pointer (same as passed to WriteCabinetState)
1216  * second one could be a size (0x0c). The size is the same as the structure saved to
1217  * HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState
1218  * I'm (js) guessing: this one is just ReadCabinetState ;-)
1219  */
1220 HRESULT WINAPI shell32_654 (DWORD x, DWORD y)
1221 {       FIXME("0x%08lx 0x%08lx stub\n",x,y);
1222         return 0;
1223 }
1224
1225 /************************************************************************
1226  *      RLBuildListOfPaths                      [SHELL32.146]
1227  *
1228  * NOTES
1229  *   builds a DPA
1230  */
1231 DWORD WINAPI RLBuildListOfPaths (void)
1232 {       FIXME("stub\n");
1233         return 0;
1234 }
1235 /************************************************************************
1236  *      SHValidateUNC                           [SHELL32.173]
1237  *
1238  */
1239 HRESULT WINAPI SHValidateUNC (DWORD x, DWORD y, DWORD z)
1240 {
1241         FIXME("0x%08lx 0x%08lx 0x%08lx stub\n",x,y,z);
1242         return 0;
1243 }
1244
1245 /************************************************************************
1246  *      DoEnvironmentSubstA                     [SHELL32.@]
1247  *
1248  */
1249 HRESULT WINAPI DoEnvironmentSubstA(LPSTR x, LPSTR y)
1250 {
1251         FIXME("(%s, %s) stub\n", debugstr_a(x), debugstr_a(y));
1252         return 0;
1253 }
1254
1255 /************************************************************************
1256  *      DoEnvironmentSubstW                     [SHELL32.@]
1257  *
1258  */
1259 HRESULT WINAPI DoEnvironmentSubstW(LPWSTR x, LPWSTR y)
1260 {
1261         FIXME("(%s, %s): stub\n", debugstr_w(x), debugstr_w(y));
1262         return 0;
1263 }
1264
1265 /************************************************************************
1266  *      DoEnvironmentSubst                      [SHELL32.53]
1267  *
1268  */
1269 HRESULT WINAPI DoEnvironmentSubstAW(LPVOID x, LPVOID y)
1270 {
1271         if (SHELL_OsIsUnicode())
1272           return DoEnvironmentSubstW(x, y);
1273         return DoEnvironmentSubstA(x, y);
1274 }
1275
1276 /*************************************************************************
1277  *      @                             [SHELL32.243]
1278  *
1279  * Win98+ by-ordinal routine.  In Win98 this routine returns zero and
1280  * does nothing else.  Possibly this does something in NT or SHELL32 5.0?
1281  *
1282  */
1283
1284 BOOL WINAPI shell32_243(DWORD a, DWORD b)
1285 {
1286   return FALSE;
1287 }
1288
1289 /*************************************************************************
1290  *      @       [SHELL32.714]
1291  */
1292 DWORD WINAPI SHELL32_714(LPVOID x)
1293 {
1294         FIXME("(%s)stub\n", debugstr_w(x));
1295         return 0;
1296 }
1297
1298 /*************************************************************************
1299  *      SHAddFromPropSheetExtArray      [SHELL32.167]
1300  */
1301 DWORD WINAPI SHAddFromPropSheetExtArray(DWORD a, DWORD b, DWORD c)
1302 {
1303         FIXME("(%08lx,%08lx,%08lx)stub\n", a, b, c);
1304         return 0;
1305 }
1306
1307 /*************************************************************************
1308  *      SHCreatePropSheetExtArray       [SHELL32.168]
1309  */
1310 DWORD WINAPI SHCreatePropSheetExtArray(DWORD a, LPCSTR b, DWORD c)
1311 {
1312         FIXME("(%08lx,%s,%08lx)stub\n", a, debugstr_a(b), c);
1313         return 0;
1314 }
1315
1316 /*************************************************************************
1317  *      SHReplaceFromPropSheetExtArray  [SHELL32.170]
1318  */
1319 DWORD WINAPI SHReplaceFromPropSheetExtArray(DWORD a, DWORD b, DWORD c, DWORD d)
1320 {
1321         FIXME("(%08lx,%08lx,%08lx,%08lx)stub\n", a, b, c, d);
1322         return 0;
1323 }
1324
1325 /*************************************************************************
1326  *      SHDestroyPropSheetExtArray      [SHELL32.169]
1327  */
1328 DWORD WINAPI SHDestroyPropSheetExtArray(DWORD a)
1329 {
1330         FIXME("(%08lx)stub\n", a);
1331         return 0;
1332 }
1333
1334 /*************************************************************************
1335  *      CIDLData_CreateFromIDArray      [SHELL32.83]
1336  *
1337  *  Create IDataObject from PIDLs??
1338  */
1339 HRESULT WINAPI CIDLData_CreateFromIDArray(
1340         LPCITEMIDLIST pidlFolder,
1341         DWORD cpidlFiles,
1342         LPCITEMIDLIST *lppidlFiles,
1343         LPDATAOBJECT *ppdataObject)
1344 {
1345     INT i;
1346     HWND hwnd = 0;   /*FIXME: who should be hwnd of owner? set to desktop */
1347
1348     TRACE("(%p, %ld, %p, %p)\n", pidlFolder, cpidlFiles, lppidlFiles, ppdataObject);
1349     if (TRACE_ON(pidl))
1350     {
1351         pdump (pidlFolder);
1352         for (i=0; i<cpidlFiles; i++) pdump (lppidlFiles[i]);
1353     }
1354     *ppdataObject = IDataObject_Constructor( hwnd, pidlFolder,
1355                                              lppidlFiles, cpidlFiles);
1356     if (*ppdataObject) return S_OK;
1357     return E_OUTOFMEMORY;
1358 }
1359
1360 /*************************************************************************
1361  * SHCreateStdEnumFmtEtc                        [SHELL32.74]
1362  *
1363  * NOTES
1364  *
1365  */
1366 HRESULT WINAPI SHCreateStdEnumFmtEtc(
1367         DWORD cFormats,
1368         const FORMATETC *lpFormats,
1369         LPENUMFORMATETC *ppenumFormatetc)
1370 {
1371         IEnumFORMATETC *pef;
1372         HRESULT hRes;
1373         TRACE("cf=%ld fe=%p pef=%p\n", cFormats, lpFormats, ppenumFormatetc);
1374
1375         pef = IEnumFORMATETC_Constructor(cFormats, lpFormats);
1376         if (!pef)
1377           return E_OUTOFMEMORY;
1378
1379         IEnumFORMATETC_AddRef(pef);
1380         hRes = IEnumFORMATETC_QueryInterface(pef, &IID_IEnumFORMATETC, (LPVOID*)ppenumFormatetc);
1381         IEnumFORMATETC_Release(pef);
1382
1383         return hRes;
1384 }