https://git.reactos.org/?p=reactos.git;a=commitdiff;h=90a5b9a83f2215085a0a628c996eeb32e60853fc

commit 90a5b9a83f2215085a0a628c996eeb32e60853fc
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Mon Jul 29 09:20:36 2024 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Mon Jul 29 09:20:36 2024 +0900

    [SHELL32] RecycleBin5: Make it C++ (#7174)
    
    Modernize code.
    JIRA issue: CORE-19595
    Rewrite RecycleBin5 in C++.
---
 dll/win32/shell32/shellrecyclebin/CMakeLists.txt   |   3 +-
 .../shell32/shellrecyclebin/recyclebin_private.h   |   3 +-
 .../{recyclebin_v5.c => recyclebin_v5.cpp}         | 401 ++++++++++-----------
 3 files changed, 195 insertions(+), 212 deletions(-)

diff --git a/dll/win32/shell32/shellrecyclebin/CMakeLists.txt 
b/dll/win32/shell32/shellrecyclebin/CMakeLists.txt
index ef5bf3da1c8..1c8f343ff65 100644
--- a/dll/win32/shell32/shellrecyclebin/CMakeLists.txt
+++ b/dll/win32/shell32/shellrecyclebin/CMakeLists.txt
@@ -8,11 +8,12 @@ list(APPEND SOURCE
     recyclebin.c
     recyclebin_generic.cpp
     recyclebin_generic_enumerator.cpp
-    recyclebin_v5.c
+    recyclebin_v5.cpp
     recyclebin_v5_enumerator.cpp
     recyclebin_private.h)
 
 add_library(recyclebin ${SOURCE} guid.c)
+target_link_libraries(recyclebin PRIVATE atl_classes)
 add_pch(recyclebin recyclebin_private.h SOURCE)
 add_dependencies(recyclebin psdk)
 target_link_libraries(recyclebin PRIVATE atl_classes)
diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h 
b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h
index aba8decdfd1..42cffd22656 100644
--- a/dll/win32/shell32/shellrecyclebin/recyclebin_private.h
+++ b/dll/win32/shell32/shellrecyclebin/recyclebin_private.h
@@ -50,6 +50,7 @@ HRESULT RecycleBinGenericEnum_Constructor(OUT 
IRecycleBinEnumList **pprbel);
 
 /* recyclebin_v5.c */
 
-HRESULT RecycleBin5_Constructor(IN LPCWSTR VolumePath, OUT IUnknown 
**ppUnknown);
+EXTERN_C
+HRESULT RecycleBin5_Constructor(_In_ LPCWSTR VolumePath, _Out_ IUnknown 
**ppUnknown);
 
 #endif /* _RECYCLEBIN_PRIVATE_H_ */
diff --git a/dll/win32/shell32/shellrecyclebin/recyclebin_v5.c 
b/dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
similarity index 65%
rename from dll/win32/shell32/shellrecyclebin/recyclebin_v5.c
rename to dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
index 3344b2c035c..a98e56861bb 100644
--- a/dll/win32/shell32/shellrecyclebin/recyclebin_v5.c
+++ b/dll/win32/shell32/shellrecyclebin/recyclebin_v5.cpp
@@ -1,13 +1,14 @@
 /*
  * PROJECT:     Recycle bin management
- * LICENSE:     GPL v2 - See COPYING in the top level directory
- * FILE:        lib/recyclebin/recyclebin_v5.c
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     Deals with recycle bins of Windows 2000/XP/2003
- * PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpous...@reactos.org)
+ * COPYRIGHT:   Copyright 2006-2007 Hervé Poussineau (hpous...@reactos.org)
+ *              Copyright 2024 Katayama Hirofumi MZ 
(katayama.hirofumi...@gmail.com)
  */
 
 #include "recyclebin_private.h"
-
+#include <atlstr.h>
+#include <shlwapi.h>
 #include "sddl.h"
 
 static BOOL
@@ -38,7 +39,7 @@ IntDeleteRecursive(
     {
         /* Prepare file specification */
         dwLength = wcslen(FullName);
-        FullPath = HeapAlloc(GetProcessHeap(), 0, (dwLength + 1 + MAX_PATH + 
1) * sizeof(WCHAR));
+        FullPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (dwLength + 1 + 
MAX_PATH + 1) * sizeof(WCHAR));
         if (!FullPath)
         {
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@@ -91,99 +92,97 @@ cleanup:
     return ret;
 }
 
-struct RecycleBin5
+class RecycleBin5 : public IRecycleBin5
 {
-    ULONG ref;
-    IRecycleBin5 recycleBinImpl;
-    HANDLE hInfo;
-    HANDLE hInfoMapped;
-
-    DWORD EnumeratorCount;
-
-    LPWSTR VolumePath;
-    WCHAR Folder[ANY_SIZE]; /* [drive]:\[RECYCLE_BIN_DIRECTORY]\{SID} */
+public:
+    RecycleBin5();
+    virtual ~RecycleBin5();
+
+    HRESULT Init(_In_ LPCWSTR VolumePath);
+
+    /* IUnknown interface */
+    STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ void **ppvObject) 
override;
+    STDMETHODIMP_(ULONG) AddRef() override;
+    STDMETHODIMP_(ULONG) Release() override;
+
+    /* IRecycleBin interface */
+    STDMETHODIMP DeleteFile(_In_ LPCWSTR szFileName) override;
+    STDMETHODIMP EmptyRecycleBin() override;
+    STDMETHODIMP EnumObjects(_Out_ IRecycleBinEnumList **ppEnumList) override;
+
+    /* IRecycleBin5 interface */
+    STDMETHODIMP Delete(
+        _In_ LPCWSTR pDeletedFileName,
+        _In_ DELETED_FILE_RECORD *pDeletedFile) override;
+    STDMETHODIMP Restore(
+        _In_ LPCWSTR pDeletedFileName,
+        _In_ DELETED_FILE_RECORD *pDeletedFile) override;
+    STDMETHODIMP OnClosing(_In_ IRecycleBinEnumList *prbel) override;
+
+protected:
+    LONG m_ref;
+    HANDLE m_hInfo;
+    HANDLE m_hInfoMapped;
+    DWORD m_EnumeratorCount;
+    CStringW m_VolumePath;
+    CStringW m_Folder; /* [drive]:\[RECYCLE_BIN_DIRECTORY]\{SID} */
 };
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_QueryInterface(
-    IRecycleBin5 *This,
-    REFIID riid,
-    void **ppvObject)
+STDMETHODIMP RecycleBin5::QueryInterface(_In_ REFIID riid, _Out_ void 
**ppvObject)
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
-
-    TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject);
+    TRACE("(%p, %s, %p)\n", this, debugstr_guid(&riid), ppvObject);
 
     if (!ppvObject)
         return E_POINTER;
 
-    if (IsEqualIID(riid, &IID_IUnknown))
-        *ppvObject = &s->recycleBinImpl;
-    else if (IsEqualIID(riid, &IID_IRecycleBin))
-        *ppvObject = &s->recycleBinImpl;
-    else if (IsEqualIID(riid, &IID_IRecycleBin5))
-        *ppvObject = &s->recycleBinImpl;
+    if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IRecycleBin))
+        *ppvObject = static_cast<IRecycleBin5 *>(this);
+    else if (IsEqualIID(riid, IID_IRecycleBin5))
+        *ppvObject = static_cast<IRecycleBin5 *>(this);
     else
     {
         *ppvObject = NULL;
         return E_NOINTERFACE;
     }
 
-    IUnknown_AddRef(This);
+    AddRef();
     return S_OK;
 }
 
-static ULONG STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_AddRef(
-    IRecycleBin5 *This)
+STDMETHODIMP_(ULONG) RecycleBin5::AddRef()
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
-    ULONG refCount = InterlockedIncrement((PLONG)&s->ref);
-    TRACE("(%p)\n", This);
-    return refCount;
+    TRACE("(%p)\n", this);
+    return InterlockedIncrement(&m_ref);
 }
 
-static VOID
-RecycleBin5_Destructor(
-    struct RecycleBin5 *s)
+RecycleBin5::~RecycleBin5()
 {
-    TRACE("(%p)\n", s);
+    TRACE("(%p)\n", this);
 
-    if (s->hInfo && s->hInfo != INVALID_HANDLE_VALUE)
-        CloseHandle(s->hInfo);
-    if (s->hInfoMapped)
-        CloseHandle(s->hInfoMapped);
-    CoTaskMemFree(s);
+    if (m_hInfo && m_hInfo != INVALID_HANDLE_VALUE)
+        CloseHandle(m_hInfo);
+    if (m_hInfoMapped)
+        CloseHandle(m_hInfoMapped);
 }
 
-static ULONG STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_Release(
-    IRecycleBin5 *This)
+STDMETHODIMP_(ULONG) RecycleBin5::Release()
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
-    ULONG refCount;
-
-    TRACE("(%p)\n", This);
-
-    refCount = InterlockedDecrement((PLONG)&s->ref);
+    TRACE("(%p)\n", this);
 
+    ULONG refCount = InterlockedDecrement(&m_ref);
     if (refCount == 0)
-        RecycleBin5_Destructor(s);
-
+        delete this;
     return refCount;
 }
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_DeleteFile(
-    IN IRecycleBin5 *This,
-    IN LPCWSTR szFileName)
+STDMETHODIMP RecycleBin5::DeleteFile(_In_ LPCWSTR szFileName)
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
     LPWSTR szFullName = NULL;
     DWORD dwBufferLength = 0;
     LPWSTR lpFilePart;
     LPCWSTR Extension;
-    WCHAR DeletedFileName[MAX_PATH];
+    CStringW DeletedFileName;
+    WCHAR szUniqueId[64];
     DWORD len;
     HANDLE hFile = INVALID_HANDLE_VALUE;
     PINFO2_HEADER pHeader = NULL;
@@ -194,9 +193,9 @@ RecycleBin5_RecycleBin5_DeleteFile(
     DWORD ClusterSize, BytesPerSector, SectorsPerCluster;
     HRESULT hr;
 
-    TRACE("(%p, %s)\n", This, debugstr_w(szFileName));
+    TRACE("(%p, %s)\n", this, debugstr_w(szFileName));
 
-    if (s->EnumeratorCount != 0)
+    if (m_EnumeratorCount != 0)
         return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
 
     /* Get full file name */
@@ -214,7 +213,7 @@ RecycleBin5_RecycleBin5_DeleteFile(
         if (szFullName)
             CoTaskMemFree(szFullName);
         dwBufferLength = len;
-        szFullName = CoTaskMemAlloc(dwBufferLength * sizeof(WCHAR));
+        szFullName = (LPWSTR)CoTaskMemAlloc(dwBufferLength * sizeof(WCHAR));
         if (!szFullName)
             return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
     }
@@ -242,18 +241,18 @@ RecycleBin5_RecycleBin5_DeleteFile(
     }
 
     /* Increase INFO2 file size */
-    CloseHandle(s->hInfoMapped);
-    SetFilePointer(s->hInfo, sizeof(DELETED_FILE_RECORD), NULL, FILE_END);
-    SetEndOfFile(s->hInfo);
-    s->hInfoMapped = CreateFileMappingW(s->hInfo, NULL, PAGE_READWRITE | 
SEC_COMMIT, 0, 0, NULL);
-    if (!s->hInfoMapped)
+    CloseHandle(m_hInfoMapped);
+    SetFilePointer(m_hInfo, sizeof(DELETED_FILE_RECORD), NULL, FILE_END);
+    SetEndOfFile(m_hInfo);
+    m_hInfoMapped = CreateFileMappingW(m_hInfo, NULL, PAGE_READWRITE | 
SEC_COMMIT, 0, 0, NULL);
+    if (!m_hInfoMapped)
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
         goto cleanup;
     }
 
     /* Open INFO2 file */
-    pHeader = MapViewOfFile(s->hInfoMapped, FILE_MAP_WRITE, 0, 0, 0);
+    pHeader = (PINFO2_HEADER)MapViewOfFile(m_hInfoMapped, FILE_MAP_WRITE, 0, 
0, 0);
     if (!pHeader)
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
@@ -261,7 +260,7 @@ RecycleBin5_RecycleBin5_DeleteFile(
     }
 
     /* Get number of entries */
-    FileSize.u.LowPart = GetFileSize(s->hInfo, &FileSize.u.HighPart);
+    FileSize.u.LowPart = GetFileSize(m_hInfo, &FileSize.u.HighPart);
     if (FileSize.u.LowPart < sizeof(INFO2_HEADER))
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
@@ -295,7 +294,7 @@ RecycleBin5_RecycleBin5_DeleteFile(
     pHeader->dwTotalLogicalSize += FileSize.u.LowPart;
 
     /* Generate new name */
-    Extension = wcsrchr(szFullName, '.');
+    Extension = PathFindExtensionW(szFullName);
     ZeroMemory(pDeletedFile, sizeof(DELETED_FILE_RECORD));
     if (dwEntries == 0)
         pDeletedFile->dwRecordUniqueId = 0;
@@ -304,11 +303,18 @@ RecycleBin5_RecycleBin5_DeleteFile(
         PDELETED_FILE_RECORD pLastDeleted = ((PDELETED_FILE_RECORD)(pHeader + 
1)) + dwEntries - 1;
         pDeletedFile->dwRecordUniqueId = pLastDeleted->dwRecordUniqueId + 1;
     }
+
     pDeletedFile->dwDriveNumber = tolower(szFullName[0]) - 'a';
-    _snwprintf(DeletedFileName, MAX_PATH, L"%s\\D%c%lu%s", s->Folder, 
pDeletedFile->dwDriveNumber + 'a', pDeletedFile->dwRecordUniqueId, Extension);
+    _ultow(pDeletedFile->dwRecordUniqueId, szUniqueId, 10);
+
+    DeletedFileName = m_Folder;
+    DeletedFileName += L"\\D";
+    DeletedFileName += (WCHAR)(L'a' + pDeletedFile->dwDriveNumber);
+    DeletedFileName += szUniqueId;
+    DeletedFileName += Extension;
 
     /* Get cluster size */
-    if (!GetDiskFreeSpaceW(s->VolumePath, &SectorsPerCluster, &BytesPerSector, 
NULL, NULL))
+    if (!GetDiskFreeSpaceW(m_VolumePath, &SectorsPerCluster, &BytesPerSector, 
NULL, NULL))
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
         goto cleanup;
@@ -348,80 +354,69 @@ cleanup:
     return hr;
 }
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_EmptyRecycleBin(
-    IN IRecycleBin5 *This)
+STDMETHODIMP RecycleBin5::EmptyRecycleBin()
 {
-    IRecycleBinEnumList *prbel;
-    IRecycleBinFile *prbf;
-    HRESULT hr;
-
-    TRACE("(%p)\n", This);
+    TRACE("(%p)\n", this);
 
     while (TRUE)
     {
-        hr = IRecycleBin5_EnumObjects(This, &prbel);
+        IRecycleBinEnumList *prbel;
+        HRESULT hr = EnumObjects(&prbel);
         if (!SUCCEEDED(hr))
             return hr;
-        hr = IRecycleBinEnumList_Next(prbel, 1, &prbf, NULL);
-        IRecycleBinEnumList_Release(prbel);
+
+        IRecycleBinFile *prbf;
+        hr = prbel->Next(1, &prbf, NULL);
+        prbel->Release();
         if (hr == S_FALSE)
             return S_OK;
-        hr = IRecycleBinFile_Delete(prbf);
-        IRecycleBinFile_Release(prbf);
+        hr = prbf->Delete();
+        prbf->Release();
         if (!SUCCEEDED(hr))
             return hr;
     }
 }
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_EnumObjects(
-    IN IRecycleBin5 *This,
-    OUT IRecycleBinEnumList **ppEnumList)
+STDMETHODIMP RecycleBin5::EnumObjects(_Out_ IRecycleBinEnumList **ppEnumList)
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
-    IRecycleBinEnumList *prbel;
-    HRESULT hr;
-    IUnknown *pUnk;
-
-    TRACE("(%p, %p)\n", This, ppEnumList);
+    TRACE("(%p, %p)\n", this, ppEnumList);
 
-    hr = RecycleBin5Enum_Constructor(This, s->hInfo, s->hInfoMapped, 
s->Folder, &pUnk);
+    IUnknown *pUnk;
+    HRESULT hr = RecycleBin5Enum_Constructor(this, m_hInfo, m_hInfoMapped, 
m_Folder, &pUnk);
     if (!SUCCEEDED(hr))
         return hr;
 
-    hr = IUnknown_QueryInterface(pUnk, &IID_IRecycleBinEnumList, (void 
**)&prbel);
+    IRecycleBinEnumList *prbel;
+    hr = pUnk->QueryInterface(IID_IRecycleBinEnumList, (void **)&prbel);
     if (SUCCEEDED(hr))
     {
-        s->EnumeratorCount++;
+        m_EnumeratorCount++;
         *ppEnumList = prbel;
     }
-    IUnknown_Release(pUnk);
+
+    pUnk->Release();
     return hr;
 }
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_Delete(
-    IN IRecycleBin5 *This,
-    IN LPCWSTR pDeletedFileName,
-    IN DELETED_FILE_RECORD *pDeletedFile)
+STDMETHODIMP RecycleBin5::Delete(
+    _In_ LPCWSTR pDeletedFileName,
+    _In_ DELETED_FILE_RECORD *pDeletedFile)
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
     ULARGE_INTEGER FileSize;
     PINFO2_HEADER pHeader;
     DELETED_FILE_RECORD *pRecord, *pLast;
     DWORD dwEntries, i;
 
-    TRACE("(%p, %s, %p)\n", This, debugstr_w(pDeletedFileName), pDeletedFile);
+    TRACE("(%p, %s, %p)\n", this, debugstr_w(pDeletedFileName), pDeletedFile);
 
-    if (s->EnumeratorCount != 0)
+    if (m_EnumeratorCount != 0)
         return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
 
-    pHeader = MapViewOfFile(s->hInfoMapped, FILE_MAP_WRITE, 0, 0, 0);
+    pHeader = (PINFO2_HEADER)MapViewOfFile(m_hInfoMapped, FILE_MAP_WRITE, 0, 
0, 0);
     if (!pHeader)
         return HRESULT_FROM_WIN32(GetLastError());
 
-    FileSize.u.LowPart = GetFileSize(s->hInfo, &FileSize.u.HighPart);
+    FileSize.u.LowPart = GetFileSize(m_hInfo, &FileSize.u.HighPart);
     if (FileSize.u.LowPart == 0)
     {
         UnmapViewOfFile(pHeader);
@@ -448,11 +443,11 @@ RecycleBin5_RecycleBin5_Delete(
             UnmapViewOfFile(pHeader);
 
             /* Resize file */
-            CloseHandle(s->hInfoMapped);
-            SetFilePointer(s->hInfo, -(LONG)sizeof(DELETED_FILE_RECORD), NULL, 
FILE_END);
-            SetEndOfFile(s->hInfo);
-            s->hInfoMapped = CreateFileMappingW(s->hInfo, NULL, PAGE_READWRITE 
| SEC_COMMIT, 0, 0, NULL);
-            if (!s->hInfoMapped)
+            CloseHandle(m_hInfoMapped);
+            SetFilePointer(m_hInfo, -(LONG)sizeof(DELETED_FILE_RECORD), NULL, 
FILE_END);
+            SetEndOfFile(m_hInfo);
+            m_hInfoMapped = CreateFileMappingW(m_hInfo, NULL, PAGE_READWRITE | 
SEC_COMMIT, 0, 0, NULL);
+            if (!m_hInfoMapped)
                 return HRESULT_FROM_WIN32(GetLastError());
             return S_OK;
         }
@@ -462,13 +457,10 @@ RecycleBin5_RecycleBin5_Delete(
     return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
 }
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_Restore(
-    IN IRecycleBin5 *This,
-    IN LPCWSTR pDeletedFileName,
-    IN DELETED_FILE_RECORD *pDeletedFile)
+STDMETHODIMP RecycleBin5::Restore(
+    _In_ LPCWSTR pDeletedFileName,
+    _In_ DELETED_FILE_RECORD *pDeletedFile)
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
     ULARGE_INTEGER FileSize;
     PINFO2_HEADER pHeader;
     DELETED_FILE_RECORD *pRecord, *pLast;
@@ -476,16 +468,16 @@ RecycleBin5_RecycleBin5_Restore(
     SHFILEOPSTRUCTW op;
     int res;
 
-    TRACE("(%p, %s, %p)\n", This, debugstr_w(pDeletedFileName), pDeletedFile);
+    TRACE("(%p, %s, %p)\n", this, debugstr_w(pDeletedFileName), pDeletedFile);
 
-    if (s->EnumeratorCount != 0)
+    if (m_EnumeratorCount != 0)
         return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
 
-    pHeader = MapViewOfFile(s->hInfoMapped, FILE_MAP_WRITE, 0, 0, 0);
+    pHeader = (PINFO2_HEADER)MapViewOfFile(m_hInfoMapped, FILE_MAP_WRITE, 0, 
0, 0);
     if (!pHeader)
         return HRESULT_FROM_WIN32(GetLastError());
 
-    FileSize.u.LowPart = GetFileSize(s->hInfo, &FileSize.u.HighPart);
+    FileSize.u.LowPart = GetFileSize(m_hInfo, &FileSize.u.HighPart);
     if (FileSize.u.LowPart == 0)
     {
         UnmapViewOfFile(pHeader);
@@ -519,11 +511,11 @@ RecycleBin5_RecycleBin5_Restore(
             UnmapViewOfFile(pHeader);
 
             /* Resize file */
-            CloseHandle(s->hInfoMapped);
-            SetFilePointer(s->hInfo, -(LONG)sizeof(DELETED_FILE_RECORD), NULL, 
FILE_END);
-            SetEndOfFile(s->hInfo);
-            s->hInfoMapped = CreateFileMappingW(s->hInfo, NULL, PAGE_READWRITE 
| SEC_COMMIT, 0, 0, NULL);
-            if (!s->hInfoMapped)
+            CloseHandle(m_hInfoMapped);
+            SetFilePointer(m_hInfo, -(LONG)sizeof(DELETED_FILE_RECORD), NULL, 
FILE_END);
+            SetEndOfFile(m_hInfo);
+            m_hInfoMapped = CreateFileMappingW(m_hInfo, NULL, PAGE_READWRITE | 
SEC_COMMIT, 0, 0, NULL);
+            if (!m_hInfoMapped)
                 return HRESULT_FROM_WIN32(GetLastError());
             return S_OK;
         }
@@ -534,34 +526,17 @@ RecycleBin5_RecycleBin5_Restore(
     return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
 }
 
-static HRESULT STDMETHODCALLTYPE
-RecycleBin5_RecycleBin5_OnClosing(
-    IN IRecycleBin5 *This,
-    IN IRecycleBinEnumList *prbel)
+STDMETHODIMP RecycleBin5::OnClosing(_In_ IRecycleBinEnumList *prbel)
 {
-    struct RecycleBin5 *s = CONTAINING_RECORD(This, struct RecycleBin5, 
recycleBinImpl);
-    TRACE("(%p, %p)\n", This, prbel);
-    s->EnumeratorCount--;
+    TRACE("(%p, %p)\n", this, prbel);
+    m_EnumeratorCount--;
     return S_OK;
 }
 
-CONST_VTBL struct IRecycleBin5Vtbl RecycleBin5Vtbl =
-{
-    RecycleBin5_RecycleBin5_QueryInterface,
-    RecycleBin5_RecycleBin5_AddRef,
-    RecycleBin5_RecycleBin5_Release,
-    RecycleBin5_RecycleBin5_DeleteFile,
-    RecycleBin5_RecycleBin5_EmptyRecycleBin,
-    RecycleBin5_RecycleBin5_EnumObjects,
-    RecycleBin5_RecycleBin5_Delete,
-    RecycleBin5_RecycleBin5_Restore,
-    RecycleBin5_RecycleBin5_OnClosing,
-};
-
 static HRESULT
 RecycleBin5_Create(
-    IN LPCWSTR Folder,
-    IN PSID OwnerSid OPTIONAL)
+    _In_ LPCWSTR Folder,
+    _In_ PSID OwnerSid OPTIONAL)
 {
     LPWSTR BufferName = NULL;
     LPWSTR Separator; /* Pointer into BufferName buffer */
@@ -573,7 +548,7 @@ RecycleBin5_Create(
     HRESULT hr;
 
     Needed = (wcslen(Folder) + 1 + max(wcslen(RECYCLE_BIN_FILE_NAME), 
wcslen(L"desktop.ini")) + 1) * sizeof(WCHAR);
-    BufferName = HeapAlloc(GetProcessHeap(), 0, Needed);
+    BufferName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, Needed);
     if (!BufferName)
     {
         hr = ERROR_NOT_ENOUGH_MEMORY;
@@ -672,37 +647,38 @@ cleanup:
     return hr;
 }
 
-HRESULT RecycleBin5_Constructor(IN LPCWSTR VolumePath, OUT IUnknown 
**ppUnknown)
+RecycleBin5::RecycleBin5()
+    : m_ref(1)
+    , m_hInfo(NULL)
+    , m_hInfoMapped(NULL)
+    , m_EnumeratorCount(0)
+{
+}
+
+HRESULT RecycleBin5::Init(_In_ LPCWSTR VolumePath)
 {
-    struct RecycleBin5 *s = NULL;
     DWORD FileSystemFlags;
     LPCWSTR RecycleBinDirectory;
     HANDLE tokenHandle = INVALID_HANDLE_VALUE;
     PTOKEN_USER TokenUserInfo = NULL;
-    LPWSTR StringSid = NULL, p;
-    DWORD Needed, DirectoryLength;
+    LPWSTR StringSid = NULL;
+    DWORD Needed;
     INT len;
     HRESULT hr;
 
-    if (!ppUnknown)
-        return E_POINTER;
+    m_VolumePath = VolumePath;
 
     /* Get information about file system */
-    if (!GetVolumeInformationW(
-        VolumePath,
-        NULL,
-        0,
-        NULL,
-        NULL,
-        &FileSystemFlags,
-        NULL,
-        0))
+    if (!GetVolumeInformationW(VolumePath, NULL, 0, NULL, NULL, 
&FileSystemFlags, NULL, 0))
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
         goto cleanup;
     }
+
     if (!(FileSystemFlags & FILE_PERSISTENT_ACLS))
+    {
         RecycleBinDirectory = RECYCLE_BIN_DIRECTORY_WITHOUT_ACL;
+    }
     else
     {
         RecycleBinDirectory = RECYCLE_BIN_DIRECTORY_WITH_ACL;
@@ -723,7 +699,7 @@ HRESULT RecycleBin5_Constructor(IN LPCWSTR VolumePath, OUT 
IUnknown **ppUnknown)
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto cleanup;
         }
-        TokenUserInfo = HeapAlloc(GetProcessHeap(), 0, Needed);
+        TokenUserInfo = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, Needed);
         if (!TokenUserInfo)
         {
             hr = E_OUTOFMEMORY;
@@ -741,55 +717,42 @@ HRESULT RecycleBin5_Constructor(IN LPCWSTR VolumePath, 
OUT IUnknown **ppUnknown)
         }
     }
 
-    DirectoryLength = wcslen(VolumePath) + wcslen(RecycleBinDirectory) + 1;
+    m_Folder = VolumePath;
+    m_Folder += RecycleBinDirectory;
     if (StringSid)
-        DirectoryLength += wcslen(StringSid) + 1;
-    DirectoryLength += 1 + wcslen(RECYCLE_BIN_FILE_NAME);
-    DirectoryLength += wcslen(VolumePath) + 1;
-    Needed = (DirectoryLength + 1) * sizeof(WCHAR);
-
-    s = CoTaskMemAlloc(sizeof(struct RecycleBin5) + Needed);
-    if (!s)
     {
-        hr = E_OUTOFMEMORY;
-        goto cleanup;
+        m_Folder += L'\\';
+        m_Folder += StringSid;
     }
-    ZeroMemory(s, sizeof(struct RecycleBin5));
-    s->recycleBinImpl.lpVtbl = &RecycleBin5Vtbl;
-    s->ref = 1;
-    if (StringSid)
-        len = swprintf(s->Folder, L"%s%s\\%s", VolumePath, 
RecycleBinDirectory, StringSid);
-    else
-        len = swprintf(s->Folder, L"%s%s", VolumePath, RecycleBinDirectory);
-    p = &s->Folder[len];
-    wcscpy(p, L"\\" RECYCLE_BIN_FILE_NAME);
-    s->hInfo = CreateFileW(s->Folder, GENERIC_READ | GENERIC_WRITE, 0, NULL, 
OPEN_EXISTING, 0, NULL);
-    if (s->hInfo == INVALID_HANDLE_VALUE && (GetLastError() == 
ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_FILE_NOT_FOUND))
-    {
-        *p = UNICODE_NULL;
-        hr = RecycleBin5_Create(s->Folder, TokenUserInfo ? 
TokenUserInfo->User.Sid : NULL);
-        *p = L'\\';
+    len = m_Folder.GetLength();
+    m_Folder += L"\\" RECYCLE_BIN_FILE_NAME;
+
+    m_hInfo = CreateFileW(m_Folder, GENERIC_READ | GENERIC_WRITE, 0, NULL, 
OPEN_EXISTING, 0, NULL);
+    if (m_hInfo == INVALID_HANDLE_VALUE &&
+        (GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == 
ERROR_FILE_NOT_FOUND))
+    {
+        m_Folder = m_Folder.Left(len);
+        hr = RecycleBin5_Create(m_Folder, TokenUserInfo ? 
TokenUserInfo->User.Sid : NULL);
+        m_Folder += L"\\" RECYCLE_BIN_FILE_NAME;
         if (!SUCCEEDED(hr))
             goto cleanup;
-        s->hInfo = CreateFileW(s->Folder, GENERIC_READ | GENERIC_WRITE, 0, 
NULL, OPEN_EXISTING, 0, NULL);
+        m_hInfo = CreateFileW(m_Folder, GENERIC_READ | GENERIC_WRITE, 0, NULL, 
OPEN_EXISTING, 0, NULL);
     }
-    if (s->hInfo == INVALID_HANDLE_VALUE)
+
+    if (m_hInfo == INVALID_HANDLE_VALUE)
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
         goto cleanup;
     }
-    s->hInfoMapped = CreateFileMappingW(s->hInfo, NULL, PAGE_READWRITE | 
SEC_COMMIT, 0, 0, NULL);
-    if (!s->hInfoMapped)
+
+    m_hInfoMapped = CreateFileMappingW(m_hInfo, NULL, PAGE_READWRITE | 
SEC_COMMIT, 0, 0, NULL);
+    if (!m_hInfoMapped)
     {
         hr = HRESULT_FROM_WIN32(GetLastError());
         goto cleanup;
     }
-    *p = UNICODE_NULL;
-    s->VolumePath = p + 1;
-    wcscpy(s->VolumePath, VolumePath);
-
-    *ppUnknown = (IUnknown *)&s->recycleBinImpl;
 
+    m_Folder = m_Folder.Left(len);
     hr = S_OK;
 
 cleanup:
@@ -798,10 +761,28 @@ cleanup:
     HeapFree(GetProcessHeap(), 0, TokenUserInfo);
     if (StringSid)
         LocalFree(StringSid);
-    if (!SUCCEEDED(hr))
+    return hr;
+}
+
+EXTERN_C
+HRESULT RecycleBin5_Constructor(_In_ LPCWSTR VolumePath, _Out_ IUnknown 
**ppUnknown)
+{
+    if (!ppUnknown)
+        return E_POINTER;
+
+    *ppUnknown = NULL;
+
+    RecycleBin5 *pThis = new RecycleBin5();
+    if (!pThis)
+        return E_OUTOFMEMORY;
+
+    HRESULT hr = pThis->Init(VolumePath);
+    if (FAILED(hr))
     {
-        if (s)
-            RecycleBin5_Destructor(s);
+        delete pThis;
+        return hr;
     }
-    return hr;
+
+    *ppUnknown = static_cast<IRecycleBin5 *>(pThis);
+    return S_OK;
 }

Reply via email to