From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winemac.drv/clipboard.c | 81 ++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-)
diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c index 93706680470..cdb4e5e02a8 100644 --- a/dlls/winemac.drv/clipboard.c +++ b/dlls/winemac.drv/clipboard.c @@ -24,6 +24,8 @@
#include "config.h"
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "macdrv.h" #include "winuser.h" #include "shellapi.h" @@ -588,6 +590,78 @@ static WCHAR *get_dos_file_name(const char *path) }
+/*********************************************************************** + * get_nt_pathname + * + * Simplified version of RtlDosPathNameToNtPathName_U. + */ +static BOOL get_nt_pathname(const WCHAR *name, UNICODE_STRING *nt_name) +{ + static const WCHAR ntprefixW[] = {'\','?','?','\'}; + static const WCHAR uncprefixW[] = {'U','N','C','\'}; + size_t len = lstrlenW(name); + WCHAR *ptr; + + nt_name->MaximumLength = (len + 8) * sizeof(WCHAR); + if (!(ptr = malloc(nt_name->MaximumLength))) return FALSE; + nt_name->Buffer = ptr; + + memcpy(ptr, ntprefixW, sizeof(ntprefixW)); + ptr += ARRAYSIZE(ntprefixW); + if (name[0] == '\' && name[1] == '\') + { + if ((name[2] == '.' || name[2] == '?') && name[3] == '\') + { + name += 4; + len -= 4; + } + else + { + memcpy(ptr, uncprefixW, sizeof(uncprefixW)); + ptr += ARRAYSIZE(uncprefixW); + name += 2; + len -= 2; + } + } + memcpy(ptr, name, (len + 1) * sizeof(WCHAR)); + ptr += len; + nt_name->Length = (ptr - nt_name->Buffer) * sizeof(WCHAR); + return TRUE; +} + + +/* based on wine_get_unix_file_name */ +static char *get_unix_file_name(const WCHAR *dosW) +{ + UNICODE_STRING nt_name; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + ULONG size = 256; + char *buffer; + + if (!get_nt_pathname(dosW, &nt_name)) return NULL; + InitializeObjectAttributes(&attr, &nt_name, 0, 0, NULL); + for (;;) + { + if (!(buffer = malloc(size))) + { + free(nt_name.Buffer); + return NULL; + } + status = wine_nt_to_unix_file_name(&attr, buffer, &size, FILE_OPEN_IF); + if (status != STATUS_BUFFER_TOO_SMALL) break; + free(buffer); + } + free(nt_name.Buffer); + if (status) + { + free(buffer); + return NULL; + } + return buffer; +} + + /************************************************************************** * import_nsfilenames_to_hdrop * @@ -861,7 +935,7 @@ static CFDataRef export_hdrop_to_filenames(void *data, size_t size) TRACE(" %s\n", dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
if (dropfiles->fWide) - unixname = wine_get_unix_file_name(p); + unixname = get_unix_file_name(p); else { int len = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0); @@ -875,7 +949,7 @@ static CFDataRef export_hdrop_to_filenames(void *data, size_t size) }
MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, buffer_len); - unixname = wine_get_unix_file_name(buffer); + unixname = get_unix_file_name(buffer); } else unixname = NULL; @@ -893,13 +967,14 @@ static CFDataRef export_hdrop_to_filenames(void *data, size_t size) p = (char*)p + strlen(p) + 1;
filename = CFStringCreateWithFileSystemRepresentation(NULL, unixname); - HeapFree(GetProcessHeap(), 0, unixname); if (!filename) { WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname)); + free(unixname); goto done; }
+ free(unixname); CFArrayAppendValue(filenames, filename); CFRelease(filename); }