shell32: read in freedesktop's recently used document list (try 2)
Damjan Jovanovic
damjan.jov at gmail.com
Wed Apr 28 13:42:19 CDT 2010
Changelog:
* shell32: read in freedesktop's recently used document list
Try 2 is a subpart of try 1 with CP_UTF8 instead of CP_ACP and better
MultiByte<->WideChar conversion.
Damjan Jovanovic
-------------- next part --------------
diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in
index 5e4a0c8..5b94116 100644
--- a/dlls/shell32/Makefile.in
+++ b/dlls/shell32/Makefile.in
@@ -5,7 +5,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = shell32.dll
IMPORTLIB = shell32
-IMPORTS = uuid shlwapi comctl32 user32 gdi32 advapi32 kernel32 ntdll
+IMPORTS = uuid shlwapi comctl32 user32 gdi32 advapi32 kernel32 ntdll wininet
DELAYIMPORTS = ole32 oleaut32 shdocvw version
C_SRCS = \
diff --git a/dlls/shell32/shellord.c b/dlls/shell32/shellord.c
index fac7a7a..3eff1f7 100644
--- a/dlls/shell32/shellord.c
+++ b/dlls/shell32/shellord.c
@@ -21,9 +21,15 @@
*/
#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
+#include <time.h>
#define COBJMACROS
@@ -47,6 +53,8 @@
#include "shlwapi.h"
#include "commdlg.h"
#include "commoncontrols.h"
+#include "wininet.h"
+#include "xmldom.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
WINE_DECLARE_DEBUG_CHANNEL(pidl);
@@ -732,6 +740,90 @@ static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPCSTR doc_name, LPCSTR n
return AddMRUData(mruhandle, buffer, *len);
}
+static WCHAR* get_file_contents(int fd)
+{
+ WCHAR *bufferW = NULL;
+ struct stat fileinfo;
+ if (fstat(fd, &fileinfo) == 0)
+ {
+ char *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, fileinfo.st_size + 1);
+ if (buffer)
+ {
+ size_t pos = 0;
+ ssize_t ret;
+ do
+ {
+ ret = read(fd, &buffer[pos], fileinfo.st_size - pos);
+ if (ret > 0)
+ pos += ret;
+ } while ((ret > 0 || errno == EINTR) && pos < fileinfo.st_size);
+
+ if (ret >= 0)
+ {
+ INT wsize = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, NULL, 0);
+ bufferW = HeapAlloc(GetProcessHeap(), 0, wsize * sizeof(WCHAR));
+ if (bufferW)
+ MultiByteToWideChar(CP_UTF8, 0, buffer, -1, bufferW, wsize);
+ }
+ HeapFree(GetProcessHeap(), 0, buffer);
+ }
+ }
+ return bufferW;
+}
+
+/* http://standards.freedesktop.org/recent-file-spec/recent-file-spec-0.2.html */
+static void update_freedesktop_recently_used(WCHAR *filename, char *recently_used)
+{
+ int fd = -1;
+ BOOL need_unlock = FALSE;
+ WCHAR *xml = NULL;
+ IXMLDOMDocument *document = NULL;
+ HRESULT hr;
+
+ fd = open(recently_used, O_CREAT | O_RDWR, 0x600);
+ if (fd < 0)
+ goto done;
+ if (lockf(fd, F_LOCK, 0) != 0)
+ goto done;
+ need_unlock = TRUE;
+ xml = get_file_contents(fd);
+ if (xml == NULL)
+ goto done;
+
+ hr = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IXMLDOMDocument, (LPVOID*)&document);
+ if (FAILED(hr))
+ goto done;
+ if (strlenW(xml) > 0)
+ {
+ BSTR xmlBstr = SysAllocString(xml);
+ if (xmlBstr)
+ {
+ VARIANT_BOOL variantBool = VARIANT_TRUE;
+ hr = IXMLDOMDocument_loadXML(document, xmlBstr, &variantBool);
+ SysFreeString(xmlBstr);
+ if (FAILED(hr) || variantBool == VARIANT_FALSE)
+ {
+ TRACE("couldn't load recently used xml\n");
+ goto done;
+ }
+ }
+ else
+ goto done;
+ }
+
+done:
+ if (fd >= 0)
+ {
+ if (need_unlock)
+ lockf(fd, F_ULOCK, 0);
+ close(fd);
+ }
+ HeapFree(GetProcessHeap(), 0, xml);
+ if (document)
+ IXMLDOMDocument_Release(document);
+}
+
/*************************************************************************
* SHAddToRecentDocs [SHELL32.@]
*
@@ -760,6 +852,7 @@ void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
UINT olderrormode;
HKEY HCUbasekey;
+ WCHAR *fullpath = NULL;
CHAR doc_name[MAX_PATH];
CHAR link_dir[MAX_PATH];
CHAR new_lnk_filepath[MAX_PATH];
@@ -880,15 +973,33 @@ void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
switch (uFlags)
{
case SHARD_PIDL:
- SHGetPathFromIDListA(pv, doc_name);
+ fullpath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
+ if (fullpath == NULL)
+ goto fail;
+ if (!SHGetPathFromIDListA(pv, doc_name))
+ goto fail;
+ if (!SHGetPathFromIDListW(pv, fullpath))
+ goto fail;
break;
case SHARD_PATHA:
+ {
+ int size;
lstrcpynA(doc_name, pv, MAX_PATH);
+ size = MultiByteToWideChar(CP_ACP, 0, doc_name, -1, NULL, 0);
+ fullpath = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+ if (fullpath == NULL)
+ goto fail;
+ MultiByteToWideChar(CP_ACP, 0, doc_name, -1, fullpath, size);
break;
+ }
case SHARD_PATHW:
WideCharToMultiByte(CP_ACP, 0, pv, -1, doc_name, MAX_PATH, NULL, NULL);
+ fullpath = HeapAlloc(GetProcessHeap(), 0, (strlenW((WCHAR*)pv) + 1) * sizeof(WCHAR));
+ if (fullpath == NULL)
+ goto fail;
+ strcpyW(fullpath, (WCHAR*)pv);
break;
default:
@@ -932,6 +1043,7 @@ void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
if (!mruhandle) {
/* MRU failed */
ERR("MRU processing failed, handle zero\n");
+ HeapFree(GetProcessHeap(), 0, fullpath);
RegCloseKey(HCUbasekey);
return;
}
@@ -1077,10 +1189,29 @@ void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)
}
}
+ /* *** JOB 3: Add a shortcut to freedesktop.org's recent documents *** */
+
+ {
+ char *home;
+ char *recently_used;
+
+ home = getenv("HOME");
+ if (home == NULL)
+ goto fail;
+ recently_used = HeapAlloc(GetProcessHeap(), 0, strlen(home) + 1 + 14 + 1);
+ if (recently_used)
+ {
+ sprintf(recently_used, "%s/.recently-used", home);
+ update_freedesktop_recently_used(fullpath, recently_used);
+ HeapFree(GetProcessHeap(), 0, recently_used);
+ }
+ }
+
fail:
CoUninitialize();
/* all done */
+ HeapFree(GetProcessHeap(), 0, fullpath);
RegCloseKey(HCUbasekey);
return;
}
More information about the wine-patches
mailing list