- Reimplement time functions using ntdll functions.
[wine/multimedia.git] / dlls / shell32 / shellord.c
blob406fd675d48a43df01a819464c9a568d02ec6874
1 /*
2 * The parameters of many functions changes between different OS versions
3 * (NT uses Unicode strings, 95 uses ASCII strings)
5 * Copyright 1997 Marcus Meissner
6 * 1998 Jürgen Schmied
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.
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.
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
22 #include "config.h"
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"
32 #include "shellapi.h"
33 #include "shlguid.h"
34 #include "shlobj.h"
35 #include "shell32_main.h"
36 #include "undocshell.h"
37 #include "pidl.h"
38 #include "shlwapi.h"
39 #include "commdlg.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(shell);
42 WINE_DECLARE_DEBUG_CHANNEL(pidl);
44 /* FIXME: !!! move CREATEMRULIST and flags to header file !!! */
45 /* !!! it is in both here and comctl32undoc.c !!! */
46 typedef struct tagCREATEMRULIST
48 DWORD cbSize; /* size of struct */
49 DWORD nMaxItems; /* max no. of items in list */
50 DWORD dwFlags; /* see below */
51 HKEY hKey; /* root reg. key under which list is saved */
52 LPCSTR lpszSubKey; /* reg. subkey */
53 PROC lpfnCompare; /* item compare proc */
54 } CREATEMRULISTA, *LPCREATEMRULISTA;
56 /* dwFlags */
57 #define MRUF_STRING_LIST 0 /* list will contain strings */
58 #define MRUF_BINARY_LIST 1 /* list will contain binary data */
59 #define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
61 extern HANDLE WINAPI CreateMRUListA(LPCREATEMRULISTA lpcml);
62 extern DWORD WINAPI FreeMRUList(HANDLE hMRUList);
63 extern INT WINAPI AddMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData);
64 extern INT WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum);
65 extern INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize);
67 /*************************************************************************
68 * ParseFieldA [internal]
70 * copies a field from a ',' delimited string
72 * first field is nField = 1
74 DWORD WINAPI ParseFieldA(
75 LPCSTR src,
76 DWORD nField,
77 LPSTR dst,
78 DWORD len)
80 WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n",debugstr_a(src),nField,dst,len);
82 if (!src || !src[0] || !dst || !len)
83 return 0;
85 /* skip n fields delimited by ',' */
86 while (nField > 1)
88 if (*src=='\0') return FALSE;
89 if (*(src++)==',') nField--;
92 /* copy part till the next ',' to dst */
93 while ( *src!='\0' && *src!=',' && (len--)>0 ) *(dst++)=*(src++);
95 /* finalize the string */
96 *dst=0x0;
98 return TRUE;
101 /*************************************************************************
102 * ParseFieldW [internal]
104 * copies a field from a ',' delimited string
106 * first field is nField = 1
108 DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len)
110 WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n", debugstr_w(src), nField, dst, len);
112 if (!src || !src[0] || !dst || !len)
113 return 0;
115 /* skip n fields delimited by ',' */
116 while (nField > 1)
118 if (*src == 0x0) return FALSE;
119 if (*src++ == ',') nField--;
122 /* copy part till the next ',' to dst */
123 while ( *src != 0x0 && *src != ',' && (len--)>0 ) *(dst++) = *(src++);
125 /* finalize the string */
126 *dst = 0x0;
128 return TRUE;
131 /*************************************************************************
132 * ParseField [SHELL32.58]
134 DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len)
136 if (SHELL_OsIsUnicode())
137 return ParseFieldW(src, nField, dst, len);
138 return ParseFieldA(src, nField, dst, len);
141 /*************************************************************************
142 * GetFileNameFromBrowse [SHELL32.63]
145 BOOL WINAPI GetFileNameFromBrowse(
146 HWND hwndOwner,
147 LPSTR lpstrFile,
148 DWORD nMaxFile,
149 LPCSTR lpstrInitialDir,
150 LPCSTR lpstrDefExt,
151 LPCSTR lpstrFilter,
152 LPCSTR lpstrTitle)
154 HMODULE hmodule;
155 FARPROC pGetOpenFileNameA;
156 OPENFILENAMEA ofn;
157 BOOL ret;
159 TRACE("%p, %s, %ld, %s, %s, %s, %s)\n",
160 hwndOwner, lpstrFile, nMaxFile, lpstrInitialDir, lpstrDefExt,
161 lpstrFilter, lpstrTitle);
163 hmodule = LoadLibraryA("comdlg32.dll");
164 if(!hmodule) return FALSE;
165 pGetOpenFileNameA = GetProcAddress(hmodule, "GetOpenFileNameA");
166 if(!pGetOpenFileNameA)
168 FreeLibrary(hmodule);
169 return FALSE;
172 memset(&ofn, 0, sizeof(ofn));
174 ofn.lStructSize = sizeof(ofn);
175 ofn.hwndOwner = hwndOwner;
176 ofn.lpstrFilter = lpstrFilter;
177 ofn.lpstrFile = lpstrFile;
178 ofn.nMaxFile = nMaxFile;
179 ofn.lpstrInitialDir = lpstrInitialDir;
180 ofn.lpstrTitle = lpstrTitle;
181 ofn.lpstrDefExt = lpstrDefExt;
182 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
183 ret = pGetOpenFileNameA(&ofn);
185 FreeLibrary(hmodule);
186 return ret;
189 /*************************************************************************
190 * SHGetSetSettings [SHELL32.68]
192 VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet)
194 if(bSet)
196 FIXME("%p 0x%08lx TRUE\n", lpss, dwMask);
198 else
200 SHGetSettings((LPSHELLFLAGSTATE)lpss,dwMask);
204 /*************************************************************************
205 * SHGetSettings [SHELL32.@]
207 * NOTES
208 * the registry path are for win98 (tested)
209 * and possibly are the same in nt40
212 VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask)
214 HKEY hKey;
215 DWORD dwData;
216 DWORD dwDataSize = sizeof (DWORD);
218 TRACE("(%p 0x%08lx)\n",lpsfs,dwMask);
220 if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
221 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
222 return;
224 if ( (SSF_SHOWEXTENSIONS & dwMask) && !RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
225 lpsfs->fShowExtensions = ((dwData == 0) ? 0 : 1);
227 if ( (SSF_SHOWINFOTIP & dwMask) && !RegQueryValueExA(hKey, "ShowInfoTip", 0, 0, (LPBYTE)&dwData, &dwDataSize))
228 lpsfs->fShowInfoTip = ((dwData == 0) ? 0 : 1);
230 if ( (SSF_DONTPRETTYPATH & dwMask) && !RegQueryValueExA(hKey, "DontPrettyPath", 0, 0, (LPBYTE)&dwData, &dwDataSize))
231 lpsfs->fDontPrettyPath = ((dwData == 0) ? 0 : 1);
233 if ( (SSF_HIDEICONS & dwMask) && !RegQueryValueExA(hKey, "HideIcons", 0, 0, (LPBYTE)&dwData, &dwDataSize))
234 lpsfs->fHideIcons = ((dwData == 0) ? 0 : 1);
236 if ( (SSF_MAPNETDRVBUTTON & dwMask) && !RegQueryValueExA(hKey, "MapNetDrvBtn", 0, 0, (LPBYTE)&dwData, &dwDataSize))
237 lpsfs->fMapNetDrvBtn = ((dwData == 0) ? 0 : 1);
239 if ( (SSF_SHOWATTRIBCOL & dwMask) && !RegQueryValueExA(hKey, "ShowAttribCol", 0, 0, (LPBYTE)&dwData, &dwDataSize))
240 lpsfs->fShowAttribCol = ((dwData == 0) ? 0 : 1);
242 if (((SSF_SHOWALLOBJECTS | SSF_SHOWSYSFILES) & dwMask) && !RegQueryValueExA(hKey, "Hidden", 0, 0, (LPBYTE)&dwData, &dwDataSize))
243 { if (dwData == 0)
244 { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0;
245 if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0;
247 else if (dwData == 1)
248 { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 1;
249 if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0;
251 else if (dwData == 2)
252 { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0;
253 if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 1;
256 RegCloseKey (hKey);
258 TRACE("-- 0x%04x\n", *(WORD*)lpsfs);
261 /*************************************************************************
262 * SHShellFolderView_Message [SHELL32.73]
264 * PARAMETERS
265 * hwndCabinet defines the explorer cabinet window that contains the
266 * shellview you need to communicate with
267 * uMsg identifying the SFVM enum to perform
268 * lParam
270 * NOTES
271 * Message SFVM_REARRANGE = 1
272 * This message gets sent when a column gets clicked to instruct the
273 * shell view to re-sort the item list. lParam identifies the column
274 * that was clicked.
276 int WINAPI SHShellFolderView_Message(
277 HWND hwndCabinet,
278 DWORD dwMessage,
279 DWORD dwParam)
281 FIXME("%p %08lx %08lx stub\n",hwndCabinet, dwMessage, dwParam);
282 return 0;
285 /*************************************************************************
286 * RegisterShellHook [SHELL32.181]
288 * PARAMS
289 * hwnd [I] window handle
290 * y [I] flag ????
292 * NOTES
293 * exported by ordinal
295 BOOL WINAPI RegisterShellHook(
296 HWND hWnd,
297 DWORD dwType)
299 FIXME("(%p,0x%08lx):stub.\n",hWnd, dwType);
300 return TRUE;
302 /*************************************************************************
303 * ShellMessageBoxW [SHELL32.182]
305 * Format and output errormessage.
307 * idText resource ID of title or LPSTR
308 * idTitle resource ID of title or LPSTR
310 * NOTES
311 * exported by ordinal
313 int WINAPIV ShellMessageBoxW(
314 HINSTANCE hInstance,
315 HWND hWnd,
316 LPCWSTR lpText,
317 LPCWSTR lpCaption,
318 UINT uType,
319 ...)
321 WCHAR szText[100],szTitle[100];
322 LPCWSTR pszText = szText, pszTitle = szTitle, pszTemp;
323 va_list args;
324 int ret;
326 va_start(args, uType);
327 /* wvsprintfA(buf,fmt, args); */
329 TRACE("(%08lx,%08lx,%p,%p,%08x)\n",
330 (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType);
332 if (!HIWORD(lpCaption))
333 LoadStringW(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
334 else
335 pszTitle = lpCaption;
337 if (!HIWORD(lpText))
338 LoadStringW(hInstance, (DWORD)lpText, szText, sizeof(szText)/sizeof(szText[0]));
339 else
340 pszText = lpText;
342 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
343 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
345 va_end(args);
347 ret = MessageBoxW(hWnd,pszTemp,pszTitle,uType);
348 LocalFree((HLOCAL)pszTemp);
349 return ret;
352 /*************************************************************************
353 * ShellMessageBoxA [SHELL32.183]
355 int WINAPIV ShellMessageBoxA(
356 HINSTANCE hInstance,
357 HWND hWnd,
358 LPCSTR lpText,
359 LPCSTR lpCaption,
360 UINT uType,
361 ...)
363 char szText[100],szTitle[100];
364 LPCSTR pszText = szText, pszTitle = szTitle, pszTemp;
365 va_list args;
366 int ret;
368 va_start(args, uType);
369 /* wvsprintfA(buf,fmt, args); */
371 TRACE("(%08lx,%08lx,%p,%p,%08x)\n",
372 (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType);
374 if (!HIWORD(lpCaption))
375 LoadStringA(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle));
376 else
377 pszTitle = lpCaption;
379 if (!HIWORD(lpText))
380 LoadStringA(hInstance, (DWORD)lpText, szText, sizeof(szText));
381 else
382 pszText = lpText;
384 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
385 pszText, 0, 0, (LPSTR)&pszTemp, 0, &args);
387 va_end(args);
389 ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType);
390 LocalFree((HLOCAL)pszTemp);
391 return ret;
394 /*************************************************************************
395 * SHRegisterDragDrop [SHELL32.86]
397 * NOTES
398 * exported by ordinal
400 HRESULT WINAPI SHRegisterDragDrop(
401 HWND hWnd,
402 LPDROPTARGET pDropTarget)
404 FIXME("(%p,%p):stub.\n", hWnd, pDropTarget);
405 if (GetShellOle()) return pRegisterDragDrop(hWnd, pDropTarget);
406 return 0;
409 /*************************************************************************
410 * SHRevokeDragDrop [SHELL32.87]
412 * NOTES
413 * exported by ordinal
415 HRESULT WINAPI SHRevokeDragDrop(HWND hWnd)
417 FIXME("(%p):stub.\n",hWnd);
418 return 0;
421 /*************************************************************************
422 * SHDoDragDrop [SHELL32.88]
424 * NOTES
425 * exported by ordinal
427 HRESULT WINAPI SHDoDragDrop(
428 HWND hWnd,
429 LPDATAOBJECT lpDataObject,
430 LPDROPSOURCE lpDropSource,
431 DWORD dwOKEffect,
432 LPDWORD pdwEffect)
434 FIXME("(%p %p %p 0x%08lx %p):stub.\n",
435 hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect);
436 return 0;
439 /*************************************************************************
440 * ArrangeWindows [SHELL32.184]
443 WORD WINAPI ArrangeWindows(
444 HWND hwndParent,
445 DWORD dwReserved,
446 LPCRECT lpRect,
447 WORD cKids,
448 CONST HWND * lpKids)
450 FIXME("(%p 0x%08lx %p 0x%04x %p):stub.\n",
451 hwndParent, dwReserved, lpRect, cKids, lpKids);
452 return 0;
455 /*************************************************************************
456 * SignalFileOpen [SHELL32.103]
458 * NOTES
459 * exported by ordinal
461 DWORD WINAPI
462 SignalFileOpen (DWORD dwParam1)
464 FIXME("(0x%08lx):stub.\n", dwParam1);
466 return 0;
469 /*************************************************************************
470 * SHADD_get_policy - helper function for SHAddToRecentDocs
472 * PARAMETERS
473 * policy [IN] policy name (null termed string) to find
474 * type [OUT] ptr to DWORD to receive type
475 * buffer [OUT] ptr to area to hold data retrieved
476 * len [IN/OUT] ptr to DWORD holding size of buffer and getting
477 * length filled
479 * RETURNS
480 * result of the SHQueryValueEx call
482 static INT SHADD_get_policy(LPSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len)
484 HKEY Policy_basekey;
485 INT ret;
487 /* Get the key for the policies location in the registry
489 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
490 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
491 0, KEY_READ, &Policy_basekey)) {
493 if (RegOpenKeyExA(HKEY_CURRENT_USER,
494 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
495 0, KEY_READ, &Policy_basekey)) {
496 TRACE("No Explorer Policies location exists. Policy wanted=%s\n",
497 policy);
498 *len = 0;
499 return ERROR_FILE_NOT_FOUND;
503 /* Retrieve the data if it exists
505 ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len);
506 RegCloseKey(Policy_basekey);
507 return ret;
511 /*************************************************************************
512 * SHADD_compare_mru - helper function for SHAddToRecentDocs
514 * PARAMETERS
515 * data1 [IN] data being looked for
516 * data2 [IN] data in MRU
517 * cbdata [IN] length from FindMRUData call (not used)
519 * RETURNS
520 * position within MRU list that data was added.
522 static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData)
524 return lstrcmpiA(data1, data2);
527 /*************************************************************************
528 * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs
530 * PARAMETERS
531 * mruhandle [IN] handle for created MRU list
532 * doc_name [IN] null termed pure doc name
533 * new_lnk_name [IN] null termed path and file name for .lnk file
534 * buffer [IN/OUT] 2048 byte area to consturct MRU data
535 * len [OUT] ptr to int to receive space used in buffer
537 * RETURNS
538 * position within MRU list that data was added.
540 static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPSTR doc_name, LPSTR new_lnk_name,
541 LPSTR buffer, INT *len)
543 LPSTR ptr;
544 INT wlen;
546 /*FIXME: Document:
547 * RecentDocs MRU data structure seems to be:
548 * +0h document file name w/ terminating 0h
549 * +nh short int w/ size of remaining
550 * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown
551 * +n+4h 10 bytes zeros - unknown
552 * +n+eh shortcut file name w/ terminating 0h
553 * +n+e+nh 3 zero bytes - unknown
556 /* Create the MRU data structure for "RecentDocs"
558 ptr = buffer;
559 lstrcpyA(ptr, doc_name);
560 ptr += (lstrlenA(buffer) + 1);
561 wlen= lstrlenA(new_lnk_name) + 1 + 12;
562 *((short int*)ptr) = wlen;
563 ptr += 2; /* step past the length */
564 *(ptr++) = 0x30; /* unknown reason */
565 *(ptr++) = 0; /* unknown, but can be 0x00, 0x01, 0x02 */
566 memset(ptr, 0, 10);
567 ptr += 10;
568 lstrcpyA(ptr, new_lnk_name);
569 ptr += (lstrlenA(new_lnk_name) + 1);
570 memset(ptr, 0, 3);
571 ptr += 3;
572 *len = ptr - buffer;
574 /* Add the new entry into the MRU list
576 return AddMRUData(mruhandle, (LPCVOID)buffer, *len);
579 /*************************************************************************
580 * SHAddToRecentDocs [SHELL32.@]
582 * PARAMETERS
583 * uFlags [IN] SHARD_PATH or SHARD_PIDL
584 * pv [IN] string or pidl, NULL clears the list
586 * NOTES
587 * exported by name
589 * FIXME: ?? MSDN shows this as a VOID
591 DWORD WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
593 /* If list is a string list lpfnCompare has the following prototype
594 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
595 * for binary lists the prototype is
596 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
597 * where cbData is the no. of bytes to compare.
598 * Need to check what return value means identical - 0?
602 UINT olderrormode;
603 HKEY HCUbasekey;
604 CHAR doc_name[MAX_PATH];
605 CHAR link_dir[MAX_PATH];
606 CHAR new_lnk_filepath[MAX_PATH];
607 CHAR new_lnk_name[MAX_PATH];
608 IMalloc *ppM;
609 LPITEMIDLIST pidl;
610 HWND hwnd = 0; /* FIXME: get real window handle */
611 INT ret;
612 DWORD data[64], datalen, type;
614 /*FIXME: Document:
615 * RecentDocs MRU data structure seems to be:
616 * +0h document file name w/ terminating 0h
617 * +nh short int w/ size of remaining
618 * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown
619 * +n+4h 10 bytes zeros - unknown
620 * +n+eh shortcut file name w/ terminating 0h
621 * +n+e+nh 3 zero bytes - unknown
624 /* See if we need to do anything.
626 datalen = 64;
627 ret=SHADD_get_policy( "NoRecentDocsHistory", &type, &data, &datalen);
628 if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) {
629 ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret);
630 return 0;
632 if (ret == ERROR_SUCCESS) {
633 if (!( (type == REG_DWORD) ||
634 ((type == REG_BINARY) && (datalen == 4)) )) {
635 ERR("Error policy data for \"NoRecentDocsHistory\" not formated correctly, type=%ld, len=%ld\n",
636 type, datalen);
637 return 0;
640 TRACE("policy value for NoRecentDocsHistory = %08lx\n", data[0]);
641 /* now test the actual policy value */
642 if ( data[0] != 0)
643 return 0;
646 /* Open key to where the necessary info is
648 /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH)
649 * and the close should be done during the _DETACH. The resulting
650 * key is stored in the DLL global data.
652 if (RegCreateKeyExA(HKEY_CURRENT_USER,
653 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
654 0, 0, 0, KEY_READ, 0, &HCUbasekey, 0)) {
655 ERR("Failed to create 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'\n");
656 return 0;
659 /* Get path to user's "Recent" directory
661 if(SUCCEEDED(SHGetMalloc(&ppM))) {
662 if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT,
663 &pidl))) {
664 SHGetPathFromIDListA(pidl, link_dir);
665 IMalloc_Free(ppM, pidl);
667 else {
668 /* serious issues */
669 link_dir[0] = 0;
670 ERR("serious issues 1\n");
672 IMalloc_Release(ppM);
674 else {
675 /* serious issues */
676 link_dir[0] = 0;
677 ERR("serious issues 2\n");
679 TRACE("Users Recent dir %s\n", link_dir);
681 /* If no input, then go clear the lists */
682 if (!pv) {
683 /* clear user's Recent dir
686 /* FIXME: delete all files in "link_dir"
688 * while( more files ) {
689 * lstrcpyA(old_lnk_name, link_dir);
690 * PathAppendA(old_lnk_name, filenam);
691 * DeleteFileA(old_lnk_name);
694 FIXME("should delete all files in %s\\ \n", link_dir);
696 /* clear MRU list
698 /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against
699 * HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer
700 * and naturally it fails w/ rc=2. It should do it against
701 * HKEY_CURRENT_USER which is where it is stored, and where
702 * the MRU routines expect it!!!!
704 RegDeleteKeyA(HCUbasekey, "RecentDocs");
705 RegCloseKey(HCUbasekey);
706 return 0;
709 /* Have data to add, the jobs to be done:
710 * 1. Add document to MRU list in registry "HKCU\Software\
711 * Microsoft\Windows\CurrentVersion\Explorer\RecentDocs".
712 * 2. Add shortcut to document in the user's Recent directory
713 * (CSIDL_RECENT).
714 * 3. Add shortcut to Start menu's Documents submenu.
717 /* Get the pure document name from the input
719 if (uFlags & SHARD_PIDL) {
720 SHGetPathFromIDListA((LPCITEMIDLIST) pv, doc_name);
722 else {
723 lstrcpyA(doc_name, (LPSTR) pv);
725 TRACE("full document name %s\n", doc_name);
726 PathStripPathA(doc_name);
727 TRACE("stripped document name %s\n", doc_name);
730 /* *** JOB 1: Update registry for ...\Explorer\RecentDocs list *** */
732 { /* on input needs:
733 * doc_name - pure file-spec, no path
734 * link_dir - path to the user's Recent directory
735 * HCUbasekey - key of ...Windows\CurrentVersion\Explorer" node
736 * creates:
737 * new_lnk_name- pure file-spec, no path for new .lnk file
738 * new_lnk_filepath
739 * - path and file name of new .lnk file
741 CREATEMRULISTA mymru;
742 HANDLE mruhandle;
743 INT len, pos, bufused, err;
744 INT i;
745 DWORD attr;
746 CHAR buffer[2048];
747 CHAR *ptr;
748 CHAR old_lnk_name[MAX_PATH];
749 short int slen;
751 mymru.cbSize = sizeof(CREATEMRULISTA);
752 mymru.nMaxItems = 15;
753 mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE;
754 mymru.hKey = HCUbasekey;
755 mymru.lpszSubKey = "RecentDocs";
756 mymru.lpfnCompare = &SHADD_compare_mru;
757 mruhandle = CreateMRUListA(&mymru);
758 if (!mruhandle) {
759 /* MRU failed */
760 ERR("MRU processing failed, handle zero\n");
761 RegCloseKey(HCUbasekey);
762 return 0;
764 len = lstrlenA(doc_name);
765 pos = FindMRUData(mruhandle, doc_name, len, 0);
767 /* Now get the MRU entry that will be replaced
768 * and delete the .lnk file for it
770 if ((bufused = EnumMRUListA(mruhandle, (pos == -1) ? 14 : pos,
771 buffer, 2048)) != -1) {
772 ptr = buffer;
773 ptr += (lstrlenA(buffer) + 1);
774 slen = *((short int*)ptr);
775 ptr += 2; /* skip the length area */
776 if (bufused >= slen + (ptr-buffer)) {
777 /* buffer size looks good */
778 ptr += 12; /* get to string */
779 len = bufused - (ptr-buffer); /* get length of buf remaining */
780 if ((lstrlenA(ptr) > 0) && (lstrlenA(ptr) <= len-1)) {
781 /* appears to be good string */
782 lstrcpyA(old_lnk_name, link_dir);
783 PathAppendA(old_lnk_name, ptr);
784 if (!DeleteFileA(old_lnk_name)) {
785 if ((attr = GetFileAttributesA(old_lnk_name)) == -1) {
786 if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) {
787 ERR("Delete for %s failed, err=%d, attr=%08lx\n",
788 old_lnk_name, err, attr);
790 else {
791 TRACE("old .lnk file %s did not exist\n",
792 old_lnk_name);
795 else {
796 ERR("Delete for %s failed, attr=%08lx\n",
797 old_lnk_name, attr);
800 else {
801 TRACE("deleted old .lnk file %s\n", old_lnk_name);
807 /* Create usable .lnk file name for the "Recent" directory
809 wsprintfA(new_lnk_name, "%s.lnk", doc_name);
810 lstrcpyA(new_lnk_filepath, link_dir);
811 PathAppendA(new_lnk_filepath, new_lnk_name);
812 i = 1;
813 olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS);
814 while (GetFileAttributesA(new_lnk_filepath) != -1) {
815 i++;
816 wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i);
817 lstrcpyA(new_lnk_filepath, link_dir);
818 PathAppendA(new_lnk_filepath, new_lnk_name);
820 SetErrorMode(olderrormode);
821 TRACE("new shortcut will be %s\n", new_lnk_filepath);
823 /* Now add the new MRU entry and data
825 pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name,
826 buffer, &len);
827 FreeMRUList(mruhandle);
828 TRACE("Updated MRU list, new doc is position %d\n", pos);
831 /* *** JOB 2: Create shortcut in user's "Recent" directory *** */
833 { /* on input needs:
834 * doc_name - pure file-spec, no path
835 * new_lnk_filepath
836 * - path and file name of new .lnk file
837 * uFlags[in] - flags on call to SHAddToRecentDocs
838 * pv[in] - document path/pidl on call to SHAddToRecentDocs
840 IShellLinkA *psl = NULL;
841 IPersistFile *pPf = NULL;
842 HRESULT hres;
843 CHAR desc[MAX_PATH];
844 WCHAR widelink[MAX_PATH];
846 CoInitialize(0);
848 hres = CoCreateInstance( &CLSID_ShellLink,
849 NULL,
850 CLSCTX_INPROC_SERVER,
851 &IID_IShellLinkA,
852 (LPVOID )&psl);
853 if(SUCCEEDED(hres)) {
855 hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile,
856 (LPVOID *)&pPf);
857 if(FAILED(hres)) {
858 /* bombed */
859 ERR("failed QueryInterface for IPersistFile %08lx\n", hres);
860 goto fail;
863 /* Set the document path or pidl */
864 if (uFlags & SHARD_PIDL) {
865 hres = IShellLinkA_SetIDList(psl, (LPCITEMIDLIST) pv);
866 } else {
867 hres = IShellLinkA_SetPath(psl, (LPCSTR) pv);
869 if(FAILED(hres)) {
870 /* bombed */
871 ERR("failed Set{IDList|Path} %08lx\n", hres);
872 goto fail;
875 lstrcpyA(desc, "Shortcut to ");
876 lstrcatA(desc, doc_name);
877 hres = IShellLinkA_SetDescription(psl, desc);
878 if(FAILED(hres)) {
879 /* bombed */
880 ERR("failed SetDescription %08lx\n", hres);
881 goto fail;
884 MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1,
885 widelink, MAX_PATH);
886 /* create the short cut */
887 hres = IPersistFile_Save(pPf, widelink, TRUE);
888 if(FAILED(hres)) {
889 /* bombed */
890 ERR("failed IPersistFile::Save %08lx\n", hres);
891 IPersistFile_Release(pPf);
892 IShellLinkA_Release(psl);
893 goto fail;
895 hres = IPersistFile_SaveCompleted(pPf, widelink);
896 IPersistFile_Release(pPf);
897 IShellLinkA_Release(psl);
898 TRACE("shortcut %s has been created, result=%08lx\n",
899 new_lnk_filepath, hres);
901 else {
902 ERR("CoCreateInstance failed, hres=%08lx\n", hres);
906 fail:
907 CoUninitialize();
909 /* all done */
910 RegCloseKey(HCUbasekey);
911 return 0;
914 /*************************************************************************
915 * SHCreateShellFolderViewEx [SHELL32.174]
917 * NOTES
918 * see IShellFolder::CreateViewObject
920 HRESULT WINAPI SHCreateShellFolderViewEx(
921 LPCSHELLFOLDERVIEWINFO psvcbi, /* [in] shelltemplate struct */
922 LPSHELLVIEW* ppv) /* [out] IShellView pointer */
924 IShellView * psf;
925 HRESULT hRes;
927 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=0x%08lx\n",
928 psvcbi->pshf, psvcbi->pidlFolder, psvcbi->lpfnCallback,
929 psvcbi->uViewMode, psvcbi->dwUser);
931 psf = IShellView_Constructor(psvcbi->pshf);
933 if (!psf)
934 return E_OUTOFMEMORY;
936 IShellView_AddRef(psf);
937 hRes = IShellView_QueryInterface(psf, &IID_IShellView, (LPVOID *)ppv);
938 IShellView_Release(psf);
940 return hRes;
942 /*************************************************************************
943 * SHWinHelp [SHELL32.127]
946 HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z)
947 { FIXME("0x%08lx 0x%08lx 0x%08lx 0x%08lx stub\n",v,w,x,z);
948 return 0;
950 /*************************************************************************
951 * SHRunControlPanel [SHELL32.161]
954 HRESULT WINAPI SHRunControlPanel (DWORD x, DWORD z)
955 { FIXME("0x%08lx 0x%08lx stub\n",x,z);
956 return 0;
959 static LPUNKNOWN SHELL32_IExplorerInterface=0;
960 /*************************************************************************
961 * SHSetInstanceExplorer [SHELL32.176]
963 * NOTES
964 * Sets the interface
966 HRESULT WINAPI SHSetInstanceExplorer (LPUNKNOWN lpUnknown)
967 { TRACE("%p\n", lpUnknown);
968 SHELL32_IExplorerInterface = lpUnknown;
969 return (HRESULT) lpUnknown;
971 /*************************************************************************
972 * SHGetInstanceExplorer [SHELL32.@]
974 * NOTES
975 * gets the interface pointer of the explorer and a reference
977 HRESULT WINAPI SHGetInstanceExplorer (LPUNKNOWN * lpUnknown)
978 { TRACE("%p\n", lpUnknown);
980 *lpUnknown = SHELL32_IExplorerInterface;
982 if (!SHELL32_IExplorerInterface)
983 return E_FAIL;
985 IUnknown_AddRef(SHELL32_IExplorerInterface);
986 return NOERROR;
988 /*************************************************************************
989 * SHFreeUnusedLibraries [SHELL32.123]
991 * NOTES
992 * exported by name
994 void WINAPI SHFreeUnusedLibraries (void)
996 FIXME("stub\n");
998 /*************************************************************************
999 * DAD_AutoScroll [SHELL32.129]
1002 DWORD WINAPI DAD_AutoScroll(HWND hwnd, LPSCROLLSAMPLES samples, LPPOINT pt)
1004 FIXME("hwnd = %p %p %p\n",hwnd,samples,pt);
1005 return 0;
1007 /*************************************************************************
1008 * DAD_DragEnter [SHELL32.130]
1011 BOOL WINAPI DAD_DragEnter(HWND hwnd)
1013 FIXME("hwnd = %p\n",hwnd);
1014 return FALSE;
1016 /*************************************************************************
1017 * DAD_DragEnterEx [SHELL32.131]
1020 BOOL WINAPI DAD_DragEnterEx(HWND hwnd, POINT p)
1022 FIXME("hwnd = %p (%ld,%ld)\n",hwnd,p.x,p.y);
1023 return FALSE;
1025 /*************************************************************************
1026 * DAD_DragMove [SHELL32.134]
1029 BOOL WINAPI DAD_DragMove(POINT p)
1031 FIXME("(%ld,%ld)\n",p.x,p.y);
1032 return FALSE;
1034 /*************************************************************************
1035 * DAD_DragLeave [SHELL32.132]
1038 BOOL WINAPI DAD_DragLeave(VOID)
1040 FIXME("\n");
1041 return FALSE;
1043 /*************************************************************************
1044 * DAD_SetDragImage [SHELL32.136]
1046 * NOTES
1047 * exported by name
1049 BOOL WINAPI DAD_SetDragImage(
1050 HIMAGELIST himlTrack,
1051 LPPOINT lppt)
1053 FIXME("%p %p stub\n",himlTrack, lppt);
1054 return 0;
1056 /*************************************************************************
1057 * DAD_ShowDragImage [SHELL32.137]
1059 * NOTES
1060 * exported by name
1062 BOOL WINAPI DAD_ShowDragImage(BOOL bShow)
1064 FIXME("0x%08x stub\n",bShow);
1065 return 0;
1067 /*************************************************************************
1068 * ReadCabinetState [SHELL32.651] NT 4.0
1071 HRESULT WINAPI ReadCabinetState(DWORD u, DWORD v)
1072 { FIXME("0x%04lx 0x%04lx stub\n",u,v);
1073 return 0;
1075 /*************************************************************************
1076 * WriteCabinetState [SHELL32.652] NT 4.0
1079 HRESULT WINAPI WriteCabinetState(DWORD u)
1080 { FIXME("0x%04lx stub\n",u);
1081 return 0;
1083 /*************************************************************************
1084 * FileIconInit [SHELL32.660]
1087 BOOL WINAPI FileIconInit(BOOL bFullInit)
1088 { FIXME("(%s)\n", bFullInit ? "true" : "false");
1089 return 0;
1091 /*************************************************************************
1092 * IsUserAdmin [SHELL32.680] NT 4.0
1095 HRESULT WINAPI IsUserAdmin(void)
1096 { FIXME("stub\n");
1097 return TRUE;
1100 /*************************************************************************
1101 * SHAllocShared [SHELL32.520]
1103 * NOTES
1104 * parameter1 is return value from HeapAlloc
1105 * parameter2 is equal to the size allocated with HeapAlloc
1106 * parameter3 is return value from GetCurrentProcessId
1108 * the return value is posted as lParam with 0x402 (WM_USER+2) to somewhere
1109 * WM_USER+2 could be the undocumented CWM_SETPATH
1110 * the allocated memory contains a pidl
1112 HGLOBAL WINAPI SHAllocShared(LPVOID psrc, DWORD size, DWORD procID)
1113 { HGLOBAL hmem;
1114 LPVOID pmem;
1116 TRACE("ptr=%p size=0x%04lx procID=0x%04lx\n",psrc,size,procID);
1117 hmem = GlobalAlloc(GMEM_FIXED, size);
1118 if (!hmem)
1119 return 0;
1121 pmem = GlobalLock (hmem);
1123 if (! pmem)
1124 return 0;
1126 memcpy (pmem, psrc, size);
1127 GlobalUnlock(hmem);
1128 return hmem;
1130 /*************************************************************************
1131 * SHLockShared [SHELL32.521]
1133 * NOTES
1134 * parameter1 is return value from SHAllocShared
1135 * parameter2 is return value from GetCurrentProcessId
1136 * the receiver of (WM_USER+2) tries to lock the HANDLE (?)
1137 * the return value seems to be a memory address
1139 LPVOID WINAPI SHLockShared(HANDLE hmem, DWORD procID)
1140 { TRACE("handle=%p procID=0x%04lx\n",hmem,procID);
1141 return GlobalLock(hmem);
1143 /*************************************************************************
1144 * SHUnlockShared [SHELL32.522]
1146 * NOTES
1147 * parameter1 is return value from SHLockShared
1149 BOOL WINAPI SHUnlockShared(LPVOID pv)
1151 TRACE("%p\n",pv);
1152 return GlobalUnlock((HANDLE)pv);
1154 /*************************************************************************
1155 * SHFreeShared [SHELL32.523]
1157 * NOTES
1158 * parameter1 is return value from SHAllocShared
1159 * parameter2 is return value from GetCurrentProcessId
1161 BOOL WINAPI SHFreeShared(
1162 HANDLE hMem,
1163 DWORD pid)
1165 TRACE("handle=%p 0x%04lx\n",hMem,pid);
1166 return (BOOL)GlobalFree(hMem);
1169 /*************************************************************************
1170 * SetAppStartingCursor [SHELL32.99]
1172 HRESULT WINAPI SetAppStartingCursor(HWND u, DWORD v)
1173 { FIXME("hwnd=%p 0x%04lx stub\n",u,v );
1174 return 0;
1176 /*************************************************************************
1177 * SHLoadOLE [SHELL32.151]
1180 HRESULT WINAPI SHLoadOLE(DWORD u)
1181 { FIXME("0x%04lx stub\n",u);
1182 return S_OK;
1184 /*************************************************************************
1185 * DriveType [SHELL32.64]
1188 HRESULT WINAPI DriveType(DWORD u)
1189 { FIXME("0x%04lx stub\n",u);
1190 return 0;
1192 /*************************************************************************
1193 * SHAbortInvokeCommand [SHELL32.198]
1196 HRESULT WINAPI SHAbortInvokeCommand(void)
1197 { FIXME("stub\n");
1198 return 1;
1200 /*************************************************************************
1201 * SHOutOfMemoryMessageBox [SHELL32.126]
1204 int WINAPI SHOutOfMemoryMessageBox(
1205 HWND hwndOwner,
1206 LPCSTR lpCaption,
1207 UINT uType)
1209 FIXME("%p %s 0x%08x stub\n",hwndOwner, lpCaption, uType);
1210 return 0;
1212 /*************************************************************************
1213 * SHFlushClipboard [SHELL32.121]
1216 HRESULT WINAPI SHFlushClipboard(void)
1217 { FIXME("stub\n");
1218 return 1;
1221 /*************************************************************************
1222 * SHWaitForFileToOpen [SHELL32.97]
1225 BOOL WINAPI SHWaitForFileToOpen(
1226 LPCITEMIDLIST pidl,
1227 DWORD dwFlags,
1228 DWORD dwTimeout)
1230 FIXME("%p 0x%08lx 0x%08lx stub\n", pidl, dwFlags, dwTimeout);
1231 return 0;
1234 /************************************************************************
1235 * @ [SHELL32.654]
1237 * NOTES: first parameter seems to be a pointer (same as passed to WriteCabinetState)
1238 * second one could be a size (0x0c). The size is the same as the structure saved to
1239 * HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState
1240 * I'm (js) guessing: this one is just ReadCabinetState ;-)
1242 HRESULT WINAPI shell32_654 (DWORD x, DWORD y)
1243 { FIXME("0x%08lx 0x%08lx stub\n",x,y);
1244 return 0;
1247 /************************************************************************
1248 * RLBuildListOfPaths [SHELL32.146]
1250 * NOTES
1251 * builds a DPA
1253 DWORD WINAPI RLBuildListOfPaths (void)
1254 { FIXME("stub\n");
1255 return 0;
1257 /************************************************************************
1258 * SHValidateUNC [SHELL32.173]
1261 HRESULT WINAPI SHValidateUNC (DWORD x, DWORD y, DWORD z)
1263 FIXME("0x%08lx 0x%08lx 0x%08lx stub\n",x,y,z);
1264 return 0;
1267 /************************************************************************
1268 * DoEnvironmentSubstA [SHELL32.@]
1271 HRESULT WINAPI DoEnvironmentSubstA(LPSTR x, LPSTR y)
1273 FIXME("(%s, %s) stub\n", debugstr_a(x), debugstr_a(y));
1274 return 0;
1277 /************************************************************************
1278 * DoEnvironmentSubstW [SHELL32.@]
1281 HRESULT WINAPI DoEnvironmentSubstW(LPWSTR x, LPWSTR y)
1283 FIXME("(%s, %s): stub\n", debugstr_w(x), debugstr_w(y));
1284 return 0;
1287 /************************************************************************
1288 * DoEnvironmentSubst [SHELL32.53]
1291 HRESULT WINAPI DoEnvironmentSubstAW(LPVOID x, LPVOID y)
1293 if (SHELL_OsIsUnicode())
1294 return DoEnvironmentSubstW(x, y);
1295 return DoEnvironmentSubstA(x, y);
1298 /*************************************************************************
1299 * @ [SHELL32.243]
1301 * Win98+ by-ordinal routine. In Win98 this routine returns zero and
1302 * does nothing else. Possibly this does something in NT or SHELL32 5.0?
1306 BOOL WINAPI shell32_243(DWORD a, DWORD b)
1308 return FALSE;
1311 /*************************************************************************
1312 * @ [SHELL32.714]
1314 DWORD WINAPI SHELL32_714(LPVOID x)
1316 FIXME("(%s)stub\n", debugstr_w(x));
1317 return 0;
1320 /*************************************************************************
1321 * SHAddFromPropSheetExtArray [SHELL32.167]
1323 DWORD WINAPI SHAddFromPropSheetExtArray(DWORD a, DWORD b, DWORD c)
1325 FIXME("(%08lx,%08lx,%08lx)stub\n", a, b, c);
1326 return 0;
1329 /*************************************************************************
1330 * SHCreatePropSheetExtArray [SHELL32.168]
1332 DWORD WINAPI SHCreatePropSheetExtArray(DWORD a, LPCSTR b, DWORD c)
1334 FIXME("(%08lx,%s,%08lx)stub\n", a, debugstr_a(b), c);
1335 return 0;
1338 /*************************************************************************
1339 * SHReplaceFromPropSheetExtArray [SHELL32.170]
1341 DWORD WINAPI SHReplaceFromPropSheetExtArray(DWORD a, DWORD b, DWORD c, DWORD d)
1343 FIXME("(%08lx,%08lx,%08lx,%08lx)stub\n", a, b, c, d);
1344 return 0;
1347 /*************************************************************************
1348 * SHDestroyPropSheetExtArray [SHELL32.169]
1350 DWORD WINAPI SHDestroyPropSheetExtArray(DWORD a)
1352 FIXME("(%08lx)stub\n", a);
1353 return 0;
1356 /*************************************************************************
1357 * CIDLData_CreateFromIDArray [SHELL32.83]
1359 * Create IDataObject from PIDLs??
1361 HRESULT WINAPI CIDLData_CreateFromIDArray(
1362 LPCITEMIDLIST pidlFolder,
1363 DWORD cpidlFiles,
1364 LPCITEMIDLIST *lppidlFiles,
1365 LPDATAOBJECT *ppdataObject)
1367 UINT i;
1368 HWND hwnd = 0; /*FIXME: who should be hwnd of owner? set to desktop */
1370 TRACE("(%p, %ld, %p, %p)\n", pidlFolder, cpidlFiles, lppidlFiles, ppdataObject);
1371 if (TRACE_ON(pidl))
1373 pdump (pidlFolder);
1374 for (i=0; i<cpidlFiles; i++) pdump (lppidlFiles[i]);
1376 *ppdataObject = IDataObject_Constructor( hwnd, pidlFolder,
1377 lppidlFiles, cpidlFiles);
1378 if (*ppdataObject) return S_OK;
1379 return E_OUTOFMEMORY;
1382 /*************************************************************************
1383 * SHCreateStdEnumFmtEtc [SHELL32.74]
1385 * NOTES
1388 HRESULT WINAPI SHCreateStdEnumFmtEtc(
1389 DWORD cFormats,
1390 const FORMATETC *lpFormats,
1391 LPENUMFORMATETC *ppenumFormatetc)
1393 IEnumFORMATETC *pef;
1394 HRESULT hRes;
1395 TRACE("cf=%ld fe=%p pef=%p\n", cFormats, lpFormats, ppenumFormatetc);
1397 pef = IEnumFORMATETC_Constructor(cFormats, lpFormats);
1398 if (!pef)
1399 return E_OUTOFMEMORY;
1401 IEnumFORMATETC_AddRef(pef);
1402 hRes = IEnumFORMATETC_QueryInterface(pef, &IID_IEnumFORMATETC, (LPVOID*)ppenumFormatetc);
1403 IEnumFORMATETC_Release(pef);
1405 return hRes;