Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
6dac2f7a
Commit
6dac2f7a
authored
Jan 30, 2015
by
Piotr Caban
Committed by
Alexandre Julliard
Feb 02, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shell32: Add partial support for Mac trash enumeration.
parent
8aba9366
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
170 additions
and
67 deletions
+170
-67
recyclebin.c
dlls/shell32/tests/recyclebin.c
+6
-12
trash.c
dlls/shell32/trash.c
+164
-55
No files found.
dlls/shell32/tests/recyclebin.c
View file @
6dac2f7a
...
...
@@ -70,12 +70,9 @@ static void test_query_recyclebin(void)
ok
(
GetTempFileNameA
(
temp_path
,
"trash"
,
0
,
buf
),
"GetTempFileName failed
\n
"
);
buf
[
strlen
(
buf
)
+
1
]
=
'\0'
;
hr
=
pSHQueryRecycleBinA
(
buf
,
&
info1
);
if
(
hr
!=
S_OK
)
todo_wine
ok
(
hr
==
S_OK
,
"SHQueryRecycleBinA failed with error 0x%x
\n
"
,
hr
);
else
{
ok
(
hr
==
S_OK
,
"SHQueryRecycleBinA failed with error 0x%x
\n
"
,
hr
);
ok
(
info1
.
i64Size
!=
0xdeadbeef
,
"i64Size not set
\n
"
);
ok
(
info1
.
i64NumItems
!=
0xdeadbeef
,
"i64NumItems not set
\n
"
);
}
ok
(
hr
==
S_OK
,
"SHQueryRecycleBinA failed with error 0x%x
\n
"
,
hr
);
ok
(
info1
.
i64Size
!=
0xdeadbeef
,
"i64Size not set
\n
"
);
ok
(
info1
.
i64NumItems
!=
0xdeadbeef
,
"i64NumItems not set
\n
"
);
/*create and send a file to the recycle bin*/
file
=
CreateFileA
(
buf
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
0
,
NULL
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"Failure to open file %s
\n
"
,
buf
);
...
...
@@ -90,12 +87,9 @@ static void test_query_recyclebin(void)
shfo
.
lpszProgressTitle
=
NULL
;
ok
(
!
pSHFileOperationA
(
&
shfo
),
"Deletion was not successful
\n
"
);
hr
=
pSHQueryRecycleBinA
(
buf
,
&
info2
);
if
(
hr
!=
S_OK
)
todo_wine
ok
(
hr
==
S_OK
,
"SHQueryRecycleBinA failed with error 0x%x
\n
"
,
hr
);
else
{
ok
(
hr
==
S_OK
,
"SHQueryRecycleBinA failed with error 0x%x
\n
"
,
hr
);
ok
(
info2
.
i64Size
==
info1
.
i64Size
+
written
,
"Expected recycle bin to have 0x%s bytes
\n
"
,
str_from_int64
(
info1
.
i64Size
+
written
));
ok
(
info2
.
i64NumItems
==
info1
.
i64NumItems
+
1
,
"Expected recycle bin to have 0x%s items
\n
"
,
str_from_int64
(
info1
.
i64NumItems
+
1
));
}
ok
(
hr
==
S_OK
,
"SHQueryRecycleBinA failed with error 0x%x
\n
"
,
hr
);
ok
(
info2
.
i64Size
==
info1
.
i64Size
+
written
,
"Expected recycle bin to have 0x%s bytes
\n
"
,
str_from_int64
(
info1
.
i64Size
+
written
));
ok
(
info2
.
i64NumItems
==
info1
.
i64NumItems
+
1
,
"Expected recycle bin to have 0x%s items
\n
"
,
str_from_int64
(
info1
.
i64NumItems
+
1
));
}
...
...
dlls/shell32/trash.c
View file @
6dac2f7a
...
...
@@ -60,6 +60,55 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
trash
);
/*
* The item ID of a trashed element is built as follows:
* NUL byte - in most PIDLs the first byte is the type so we keep it constant
* WIN32_FIND_DATAW structure - with data about original file attributes
* bucket name - currently only an empty string meaning the home bucket is supported
* trash file name - a NUL-terminated string
*/
static
HRESULT
TRASH_CreateSimplePIDL
(
LPCSTR
filename
,
const
WIN32_FIND_DATAW
*
data
,
LPITEMIDLIST
*
pidlOut
)
{
LPITEMIDLIST
pidl
=
SHAlloc
(
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
+
lstrlenA
(
filename
)
+
1
+
2
);
*
pidlOut
=
NULL
;
if
(
pidl
==
NULL
)
return
E_OUTOFMEMORY
;
pidl
->
mkid
.
cb
=
(
USHORT
)(
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
+
lstrlenA
(
filename
)
+
1
);
pidl
->
mkid
.
abID
[
0
]
=
0
;
memcpy
(
pidl
->
mkid
.
abID
+
1
,
data
,
sizeof
(
WIN32_FIND_DATAW
));
pidl
->
mkid
.
abID
[
1
+
sizeof
(
WIN32_FIND_DATAW
)]
=
0
;
lstrcpyA
((
LPSTR
)(
pidl
->
mkid
.
abID
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
),
filename
);
*
(
USHORT
*
)(
pidl
->
mkid
.
abID
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
+
lstrlenA
(
filename
)
+
1
)
=
0
;
*
pidlOut
=
pidl
;
return
S_OK
;
}
/***********************************************************************
* TRASH_UnpackItemID [Internal]
*
* DESCRIPTION:
* Extract the information stored in an Item ID. The WIN32_FIND_DATA contains
* the information about the original file. The data->ftLastAccessTime contains
* the deletion time
*
* PARAMETER(S):
* [I] id : the ID of the item
* [O] data : the WIN32_FIND_DATA of the original file. Can be NULL is not needed
*/
HRESULT
TRASH_UnpackItemID
(
LPCSHITEMID
id
,
WIN32_FIND_DATAW
*
data
)
{
if
(
id
->
cb
<
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
2
)
return
E_INVALIDARG
;
if
(
id
->
abID
[
0
]
!=
0
||
id
->
abID
[
1
+
sizeof
(
WIN32_FIND_DATAW
)]
!=
0
)
return
E_INVALIDARG
;
if
(
memchr
(
id
->
abID
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
,
0
,
id
->
cb
-
(
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
))
==
NULL
)
return
E_INVALIDARG
;
if
(
data
!=
NULL
)
*
data
=
*
(
const
WIN32_FIND_DATAW
*
)(
id
->
abID
+
1
);
return
S_OK
;
}
#ifdef HAVE_CORESERVICES_CORESERVICES_H
BOOL
TRASH_CanTrashFile
(
LPCWSTR
wszPath
)
...
...
@@ -100,16 +149,125 @@ BOOL TRASH_TrashFile(LPCWSTR wszPath)
return
(
status
==
noErr
);
}
HRESULT
TRASH_EnumItems
(
const
WCHAR
*
path
,
LPITEMIDLIST
**
pidls
,
int
*
count
)
/* TODO:
* - set file deletion time
* - set original file location
*/
HRESULT
TRASH_GetDetails
(
const
char
*
trash_path
,
const
char
*
name
,
WIN32_FIND_DATAW
*
data
)
{
FIXME
(
"stub!
\n
"
);
return
E_NOTIMPL
;
static
int
once
;
int
trash_path_length
=
lstrlenA
(
trash_path
);
int
name_length
=
lstrlenA
(
name
);
char
*
path
=
SHAlloc
(
trash_path_length
+
1
+
name_length
+
1
);
struct
stat
stats
;
int
ret
;
if
(
!
once
++
)
FIXME
(
"semi-stub
\n
"
);
if
(
!
path
)
return
E_OUTOFMEMORY
;
memcpy
(
path
,
trash_path
,
trash_path_length
);
path
[
trash_path_length
]
=
'/'
;
memcpy
(
path
+
trash_path_length
+
1
,
name
,
name_length
+
1
);
ret
=
lstat
(
path
,
&
stats
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
if
(
ret
==
-
1
)
return
S_FALSE
;
memset
(
data
,
0
,
sizeof
(
*
data
));
data
->
nFileSizeHigh
=
stats
.
st_size
>>
32
;
data
->
nFileSizeLow
=
stats
.
st_size
&
0xffffffff
;
RtlSecondsSince1970ToTime
(
stats
.
st_mtime
,
(
LARGE_INTEGER
*
)
&
data
->
ftLastWriteTime
);
if
(
!
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
name
,
-
1
,
data
->
cFileName
,
MAX_PATH
))
return
S_FALSE
;
return
S_OK
;
}
HRESULT
TRASH_
UnpackItemID
(
LPCSHITEMID
id
,
WIN32_FIND_DATAW
*
data
)
HRESULT
TRASH_
EnumItems
(
const
WCHAR
*
path
,
LPITEMIDLIST
**
pidls
,
int
*
count
)
{
FIXME
(
"stub!
\n
"
);
return
E_NOTIMPL
;
WCHAR
volume_path
[
MAX_PATH
];
char
*
unix_path
,
trash_path
[
MAX_PATH
];
FSCatalogInfo
catalog_info
;
OSStatus
status
;
FSRef
ref
;
struct
dirent
*
entry
;
DIR
*
dir
;
LPITEMIDLIST
*
ret
;
int
i
=
0
,
ret_size
=
8
;
HRESULT
hr
;
TRACE
(
"(%s %p %p)
\n
"
,
debugstr_w
(
path
),
pidls
,
count
);
if
(
!
path
)
{
FIXME
(
"All trashes enumeration not supported
\n
"
);
volume_path
[
0
]
=
'C'
;
volume_path
[
1
]
=
':'
;
volume_path
[
2
]
=
0
;
}
else
{
if
(
!
GetVolumePathNameW
(
path
,
volume_path
,
MAX_PATH
))
return
E_FAIL
;
}
if
(
!
(
unix_path
=
wine_get_unix_file_name
(
volume_path
)))
return
E_OUTOFMEMORY
;
status
=
FSPathMakeRef
((
UInt8
*
)
unix_path
,
&
ref
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
unix_path
);
if
(
status
!=
noErr
)
return
E_FAIL
;
status
=
FSGetCatalogInfo
(
&
ref
,
kFSCatInfoVolume
,
&
catalog_info
,
NULL
,
NULL
,
NULL
);
if
(
status
!=
noErr
)
return
E_FAIL
;
status
=
FSFindFolder
(
catalog_info
.
volume
,
kTrashFolderType
,
kCreateFolder
,
&
ref
);
if
(
status
!=
noErr
)
return
E_FAIL
;
status
=
FSRefMakePath
(
&
ref
,
(
UInt8
*
)
trash_path
,
MAX_PATH
);
if
(
status
!=
noErr
)
return
E_FAIL
;
if
(
!
(
dir
=
opendir
(
trash_path
)))
return
E_FAIL
;
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
ret_size
*
sizeof
(
*
ret
));
if
(
!
ret
)
{
closedir
(
dir
);
return
E_OUTOFMEMORY
;
}
while
((
entry
=
readdir
(
dir
)))
{
WIN32_FIND_DATAW
data
;
if
(
!
lstrcmpA
(
entry
->
d_name
,
"."
)
||
!
lstrcmpA
(
entry
->
d_name
,
".."
)
||
!
lstrcmpA
(
entry
->
d_name
,
".DS_Store"
))
continue
;
if
(
i
==
ret_size
)
{
LPITEMIDLIST
*
resized
;
ret_size
*=
2
;
resized
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
ret
,
ret_size
*
sizeof
(
*
ret
));
if
(
!
resized
)
hr
=
E_OUTOFMEMORY
;
else
ret
=
resized
;
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
TRASH_GetDetails
(
trash_path
,
entry
->
d_name
,
&
data
);
if
(
hr
==
S_FALSE
)
continue
;
}
if
(
SUCCEEDED
(
hr
))
hr
=
TRASH_CreateSimplePIDL
(
entry
->
d_name
,
&
data
,
ret
+
i
);
if
(
FAILED
(
hr
))
{
while
(
i
>
0
)
SHFree
(
ret
+
(
--
i
));
HeapFree
(
GetProcessHeap
(),
0
,
ret
);
closedir
(
dir
);
return
hr
;
}
i
++
;
}
closedir
(
dir
);
*
pidls
=
SHAlloc
(
sizeof
(
**
pidls
)
*
i
);
if
(
!*
pidls
)
{
while
(
i
>
0
)
SHFree
(
ret
+
(
--
i
));
HeapFree
(
GetProcessHeap
(),
0
,
ret
);
return
E_OUTOFMEMORY
;
}
*
count
=
i
;
for
(
i
--
;
i
>=
0
;
i
--
)
(
*
pidls
)[
i
]
=
ret
[
i
];
HeapFree
(
GetProcessHeap
(),
0
,
ret
);
return
S_OK
;
}
HRESULT
TRASH_RestoreItem
(
LPCITEMIDLIST
pidl
)
...
...
@@ -388,55 +546,6 @@ BOOL TRASH_TrashFile(LPCWSTR wszPath)
return
result
;
}
/*
* The item ID of a trashed element is built as follows:
* NUL byte - in most PIDLs the first byte is the type so we keep it constant
* WIN32_FIND_DATAW structure - with data about original file attributes
* bucket name - currently only an empty string meaning the home bucket is supported
* trash file name - a NUL-terminated string
*/
static
HRESULT
TRASH_CreateSimplePIDL
(
LPCSTR
filename
,
const
WIN32_FIND_DATAW
*
data
,
LPITEMIDLIST
*
pidlOut
)
{
LPITEMIDLIST
pidl
=
SHAlloc
(
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
+
lstrlenA
(
filename
)
+
1
+
2
);
*
pidlOut
=
NULL
;
if
(
pidl
==
NULL
)
return
E_OUTOFMEMORY
;
pidl
->
mkid
.
cb
=
(
USHORT
)(
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
+
lstrlenA
(
filename
)
+
1
);
pidl
->
mkid
.
abID
[
0
]
=
0
;
memcpy
(
pidl
->
mkid
.
abID
+
1
,
data
,
sizeof
(
WIN32_FIND_DATAW
));
pidl
->
mkid
.
abID
[
1
+
sizeof
(
WIN32_FIND_DATAW
)]
=
0
;
lstrcpyA
((
LPSTR
)(
pidl
->
mkid
.
abID
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
),
filename
);
*
(
USHORT
*
)(
pidl
->
mkid
.
abID
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
+
lstrlenA
(
filename
)
+
1
)
=
0
;
*
pidlOut
=
pidl
;
return
S_OK
;
}
/***********************************************************************
* TRASH_UnpackItemID [Internal]
*
* DESCRIPTION:
* Extract the information stored in an Item ID. The WIN32_FIND_DATA contains
* the information about the original file. The data->ftLastAccessTime contains
* the deletion time
*
* PARAMETER(S):
* [I] id : the ID of the item
* [O] data : the WIN32_FIND_DATA of the original file. Can be NULL is not needed
*/
HRESULT
TRASH_UnpackItemID
(
LPCSHITEMID
id
,
WIN32_FIND_DATAW
*
data
)
{
if
(
id
->
cb
<
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
2
)
return
E_INVALIDARG
;
if
(
id
->
abID
[
0
]
!=
0
||
id
->
abID
[
1
+
sizeof
(
WIN32_FIND_DATAW
)]
!=
0
)
return
E_INVALIDARG
;
if
(
memchr
(
id
->
abID
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
,
0
,
id
->
cb
-
(
2
+
1
+
sizeof
(
WIN32_FIND_DATAW
)
+
1
))
==
NULL
)
return
E_INVALIDARG
;
if
(
data
!=
NULL
)
*
data
=
*
(
const
WIN32_FIND_DATAW
*
)(
id
->
abID
+
1
);
return
S_OK
;
}
static
HRESULT
TRASH_GetDetails
(
const
TRASH_BUCKET
*
bucket
,
LPCSTR
filename
,
WIN32_FIND_DATAW
*
data
)
{
LPSTR
path
=
NULL
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment