if (OwnerSid)\r
{\r
//DWORD rc;\r
- \r
+\r
/* Add ACL to allow only user/SYSTEM to open it */\r
/* FIXME: rc = SetNamedSecurityInfo(\r
BufferName,\r
}\r
CloseHandle(hFile);\r
hFile = INVALID_HANDLE_VALUE;\r
- \r
+\r
/* Create empty INFO2 file */\r
wcscpy(FileName, RECYCLE_BIN_FILE_NAME);\r
hFile = CreateFileW(BufferName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);\r
if (hFile != INVALID_HANDLE_VALUE)\r
CloseHandle(hFile);\r
}\r
- return ret; \r
+ return ret;\r
}\r
\r
PRECYCLE_BIN\r
- Empty a recycle bin containing directories (v5)\r
- Set security on recycle bin folder\r
- Delete files > 4Gb\r
+- Make the library thread-safe\r
\r
3 levels\r
- 1: recyclebin.c: Public interface\r
IN HANDLE hDeletedFile)\r
{\r
BOOL ret = FALSE;\r
- \r
+\r
if (!IntCheckDeletedFileHandle(hDeletedFile))\r
SetLastError(ERROR_INVALID_HANDLE);\r
else\r
PDELETED_FILE_HANDLE file = (PDELETED_FILE_HANDLE)hDeletedFile;\r
ret = DereferenceHandle(&file->refCount);\r
}\r
- \r
+\r
return ret;\r
}\r
\r
int len;\r
LPWSTR FileNameW = NULL;\r
BOOL ret = FALSE;\r
- \r
+\r
+ /* Check parameters */\r
+ if (FileName == NULL)\r
+ {\r
+ SetLastError(ERROR_INVALID_PARAMETER);\r
+ goto cleanup;\r
+ }\r
+\r
len = MultiByteToWideChar(CP_ACP, 0, FileName, -1, NULL, 0);\r
if (len == 0)\r
goto cleanup;\r
PRECYCLE_BIN bin = NULL;\r
BOOL ret = FALSE;\r
\r
+ /* Check parameters */\r
+ if (FileName == NULL)\r
+ {\r
+ SetLastError(ERROR_INVALID_PARAMETER);\r
+ goto cleanup;\r
+ }\r
+\r
/* Get full file name */\r
while (TRUE)\r
{\r
EnumerateRecycleBinA(\r
IN CHAR driveLetter,\r
IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,\r
- IN PVOID Context)\r
+ IN PVOID Context OPTIONAL)\r
{\r
return EnumerateRecycleBinW((WCHAR)driveLetter, pFnCallback, Context);\r
}\r
EnumerateRecycleBinW(\r
IN WCHAR driveLetter,\r
IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,\r
- IN PVOID Context)\r
+ IN PVOID Context OPTIONAL)\r
{\r
PRECYCLE_BIN bin = NULL;\r
BOOL ret = FALSE;\r
\r
+ /* Check parameters */\r
+ if (pFnCallback == NULL)\r
+ {\r
+ SetLastError(ERROR_INVALID_PARAMETER);\r
+ goto cleanup;\r
+ }\r
+\r
/* Open recycle bin */\r
bin = IntReferenceRecycleBin(driveLetter);\r
if (!bin)\r
GetDeletedFileDetailsA(\r
IN HANDLE hDeletedFile,\r
IN DWORD BufferSize,\r
- IN OUT PDELETED_FILE_DETAILS_A FileDetails,\r
+ IN OUT PDELETED_FILE_DETAILS_A FileDetails OPTIONAL,\r
OUT LPDWORD RequiredSize OPTIONAL)\r
{\r
PDELETED_FILE_DETAILS_W FileDetailsW = NULL;\r
GetDeletedFileDetailsW(\r
IN HANDLE hDeletedFile,\r
IN DWORD BufferSize,\r
- IN OUT PDELETED_FILE_DETAILS_W FileDetails,\r
+ IN OUT PDELETED_FILE_DETAILS_W FileDetails OPTIONAL,\r
OUT LPDWORD RequiredSize OPTIONAL)\r
{\r
BOOL ret = FALSE;\r
EnumerateRecycleBinA(\r
IN CHAR driveLetter,\r
IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,\r
- IN PVOID Context);\r
+ IN PVOID Context OPTIONAL);\r
BOOL WINAPI\r
EnumerateRecycleBinW(\r
IN WCHAR driveLetter,\r
IN PENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,\r
- IN PVOID Context);\r
+ IN PVOID Context OPTIONAL);\r
#ifdef UNICODE\r
#define EnumerateRecycleBin EnumerateRecycleBinW\r
#else\r
GetDeletedFileDetailsA(\r
IN HANDLE hDeletedFile,\r
IN DWORD BufferSize,\r
- IN OUT PDELETED_FILE_DETAILS_A FileDetails,\r
+ IN OUT PDELETED_FILE_DETAILS_A FileDetails OPTIONAL,\r
OUT LPDWORD RequiredSize OPTIONAL);\r
BOOL WINAPI\r
GetDeletedFileDetailsW(\r
IN HANDLE hDeletedFile,\r
IN DWORD BufferSize,\r
- IN OUT PDELETED_FILE_DETAILS_W FileDetails,\r
+ IN OUT PDELETED_FILE_DETAILS_W FileDetails OPTIONAL,\r
OUT LPDWORD RequiredSize OPTIONAL);\r
#ifdef UNICODE\r
#define GetDeletedFileDetails GetDeletedFileDetailsW\r
struct _REFCOUNT_DATA;\r
typedef struct _REFCOUNT_DATA *PREFCOUNT_DATA;\r
\r
-typedef BOOL (*PINT_ENUMERATE_RECYCLEBIN_CALLBACK)(IN PVOID Context, IN HANDLE hDeletedFile);\r
+typedef BOOL (*PINT_ENUMERATE_RECYCLEBIN_CALLBACK)(IN PVOID Context OPTIONAL, IN HANDLE hDeletedFile);\r
typedef BOOL (*PDESTROY_DATA) (IN PREFCOUNT_DATA pData);\r
\r
typedef BOOL (*PCLOSE_HANDLE) (IN HANDLE hHandle);\r
typedef BOOL (*PDELETE_FILE) (IN PRECYCLE_BIN bin, IN LPCWSTR FullPath, IN LPCWSTR FileName);\r
typedef BOOL (*PEMPTY_RECYCLEBIN)(IN PRECYCLE_BIN* bin);\r
-typedef BOOL (*PENUMERATE_FILES) (IN PRECYCLE_BIN bin, IN PINT_ENUMERATE_RECYCLEBIN_CALLBACK pFnCallback, IN PVOID Context);\r
-typedef BOOL (*PGET_DETAILS) (IN PRECYCLE_BIN bin, IN HANDLE hDeletedFile, IN DWORD BufferSize, IN OUT PDELETED_FILE_DETAILS_W FileDetails, OUT LPDWORD RequiredSize OPTIONAL);\r
+typedef BOOL (*PENUMERATE_FILES) (IN PRECYCLE_BIN bin, IN PINT_ENUMERATE_RECYCLEBIN_CALLBACK pFnCallback, IN PVOID Context OPTIONAL);\r
+typedef BOOL (*PGET_DETAILS) (IN PRECYCLE_BIN bin, IN HANDLE hDeletedFile, IN DWORD BufferSize, IN OUT PDELETED_FILE_DETAILS_W FileDetails OPTIONAL, OUT LPDWORD RequiredSize OPTIONAL);\r
typedef BOOL (*PRESTORE_FILE) (IN PRECYCLE_BIN bin, IN HANDLE hDeletedFile);\r
\r
typedef struct _RECYCLEBIN_CALLBACKS\r
EnumerateFiles5(\r
IN PRECYCLE_BIN bin,\r
IN PINT_ENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,\r
- IN PVOID Context)\r
+ IN PVOID Context OPTIONAL)\r
{\r
INFO2_HEADER Header;\r
DELETED_FILE_RECORD DeletedFile;\r
DWORD bytesRead, dwEntries;\r
BOOL ret = FALSE;\r
- \r
+\r
if (SetFilePointer(bin->hInfo, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)\r
goto cleanup;\r
if (!ReadFile(bin->hInfo, &Header, sizeof(INFO2_HEADER), &bytesRead, NULL))\r
if (SetFilePointer(bin->hInfo, sizeof(INFO2_HEADER) + Header.dwRecordSize * dwEntries, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)\r
goto cleanup;\r
}\r
- \r
+\r
ret = TRUE;\r
\r
cleanup:\r
IN PRECYCLE_BIN bin,\r
IN HANDLE hDeletedFile,\r
IN DWORD BufferSize,\r
- IN OUT PDELETED_FILE_DETAILS_W FileDetails,\r
+ IN OUT PDELETED_FILE_DETAILS_W FileDetails OPTIONAL,\r
OUT LPDWORD RequiredSize OPTIONAL)\r
{\r
DELETED_FILE_RECORD DeletedFile;\r
HANDLE hFile = INVALID_HANDLE_VALUE;\r
BOOL ret = FALSE;\r
\r
+ /* Check parameters */\r
+ if (BufferSize > 0 && FileDetails == NULL)\r
+ {\r
+ SetLastError(ERROR_INVALID_PARAMETER);\r
+ goto cleanup;\r
+ }\r
+\r
if (!IntSearchRecord(bin, hDeletedFile, &DeletedFile, NULL))\r
goto cleanup;\r
- Needed = (DWORD)FIELD_OFFSET(DELETED_FILE_DETAILS_W, FileName) + (wcslen(DeletedFile.FileNameW) + 1) * sizeof(WCHAR);\r
+ Needed = FIELD_OFFSET(DELETED_FILE_DETAILS_W, FileName) + (wcslen(DeletedFile.FileNameW) + 1) * sizeof(WCHAR);\r
if (RequiredSize)\r
*RequiredSize = (DWORD)Needed;\r
if (Needed > BufferSize)\r
DELETED_FILE_RECORD DeletedFile, LastFile;\r
LPWSTR FullName = NULL;\r
BOOL ret = FALSE;\r
- \r
+\r
if (SetFilePointer(bin->hInfo, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)\r
goto cleanup;\r
if (!ReadFile(bin->hInfo, &Header, sizeof(INFO2_HEADER), &bytesRead, NULL))\r
/* Restore file */\r
if (!MoveFileW(FullName, DeletedFile.FileNameW))\r
goto cleanup;\r
- \r
+\r
/* Update INFO2 */\r
/* 1) If not last entry, copy last entry to the current one */\r
if (SetFilePointer(bin->hInfo, -sizeof(DELETED_FILE_RECORD), NULL, FILE_END) == INVALID_SET_FILE_POINTER)\r
\r
if (!IntGetFullName(bin, &DeletedFile, &FullName))\r
goto cleanup;\r
- \r
+\r
if (!IntDeleteRecursive(FullName))\r
goto cleanup;\r
ret = TRUE;\r
DELETED_FILE_RECORD DeletedFile;\r
DWORD bytesRead, dwEntries;\r
BOOL ret = FALSE;\r
- \r
+\r
if (SetFilePointer(bin->hInfo, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)\r
goto cleanup;\r
if (!ReadFile(bin->hInfo, &Header, sizeof(INFO2_HEADER), &bytesRead, NULL))\r
\r
static BOOL\r
DeleteFile5(\r
- IN PRECYCLE_BIN Context,\r
+ IN PRECYCLE_BIN bin,\r
IN LPCWSTR FullPath,\r
IN LPCWSTR FileName);\r
\r
EnumerateFiles5(\r
IN PRECYCLE_BIN bin,\r
IN PINT_ENUMERATE_RECYCLEBIN_CALLBACK pFnCallback,\r
- IN PVOID Context);\r
+ IN PVOID Context OPTIONAL);\r
\r
static BOOL\r
GetDetails5(\r
IN PRECYCLE_BIN bin,\r
IN HANDLE hDeletedFile,\r
IN DWORD BufferSize,\r
- IN OUT PDELETED_FILE_DETAILS_W FileDetails,\r
+ IN OUT PDELETED_FILE_DETAILS_W FileDetails OPTIONAL,\r
OUT LPDWORD RequiredSize OPTIONAL);\r
\r
static BOOL\r
RestoreFile5(\r
- IN PRECYCLE_BIN Context,\r
+ IN PRECYCLE_BIN bin,\r
IN HANDLE hDeletedFile);\r
\r
static BOOL\r