[Bf-blender-cvs] [721a9bc35c3] master: Fix T97338: Correct reference count for COM handling and removal of gotos

Robert Guetzkow noreply at git.blender.org
Tue Apr 19 16:41:03 CEST 2022


Commit: 721a9bc35c3fed923c6cf5cfe1052d9cda168fd5
Author: Robert Guetzkow
Date:   Tue Apr 19 16:27:19 2022 +0200
Branches: master
https://developer.blender.org/rB721a9bc35c3fed923c6cf5cfe1052d9cda168fd5

Fix T97338: Correct reference count for COM handling and removal of gotos

The fix ensures that the reference count for `IShellItem *pSI` is decremented,
preventing a memory leak. For `IFileOperation *pfo` the decrement of the
reference count is only attempted when `CoCreateInstance` is successful.
Additionally, the gotos have been replaced with nested if/else statements.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D14681

===================================================================

M	source/blender/blenlib/intern/fileops.c

===================================================================

diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index 26a0479f445..5ca6fe2efd0 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -301,56 +301,60 @@ static bool delete_soft(const wchar_t *path_16, const char **error_message)
   /* Deletes file or directory to recycling bin. The latter moves all contained files and
    * directories recursively to the recycling bin as well. */
   IFileOperation *pfo;
-  IShellItem *pSI;
+  IShellItem *psi;
 
   HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
 
-  if (FAILED(hr)) {
-    *error_message = "Failed to initialize COM";
-    goto error_1;
-  }
-
-  hr = CoCreateInstance(
-      &CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
-  if (FAILED(hr)) {
-    *error_message = "Failed to create FileOperation instance";
-    goto error_2;
-  }
-
-  /* Flags for deletion:
-   * FOF_ALLOWUNDO: Enables moving file to recycling bin.
-   * FOF_SILENT: Don't show progress dialog box.
-   * FOF_WANTNUKEWARNING: Show dialog box if file can't be moved to recycling bin. */
-  hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING);
-
-  if (FAILED(hr)) {
-    *error_message = "Failed to set operation flags";
-    goto error_2;
-  }
-
-  hr = SHCreateItemFromParsingName(path_16, NULL, &IID_IShellItem, (void **)&pSI);
-  if (FAILED(hr)) {
-    *error_message = "Failed to parse path";
-    goto error_2;
-  }
-
-  hr = pfo->lpVtbl->DeleteItem(pfo, pSI, NULL);
-  if (FAILED(hr)) {
-    *error_message = "Failed to prepare delete operation";
-    goto error_2;
+  if (SUCCEEDED(hr)) {
+    /* This is also the case when COM was previously initialized and CoInitializeEx returns
+     * S_FALSE, which is not an error. Both HRESULT values S_OK and S_FALSE indicate success. */
+
+    hr = CoCreateInstance(
+        &CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
+
+    if (SUCCEEDED(hr)) {
+      /* Flags for deletion:
+       * FOF_ALLOWUNDO: Enables moving file to recycling bin.
+       * FOF_SILENT: Don't show progress dialog box.
+       * FOF_WANTNUKEWARNING: Show dialog box if file can't be moved to recycling bin. */
+      hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING);
+
+      if (SUCCEEDED(hr)) {
+        hr = SHCreateItemFromParsingName(path_16, NULL, &IID_IShellItem, (void **)&psi);
+
+        if (SUCCEEDED(hr)) {
+          hr = pfo->lpVtbl->DeleteItem(pfo, psi, NULL);
+
+          if (SUCCEEDED(hr)) {
+            hr = pfo->lpVtbl->PerformOperations(pfo);
+
+            if (FAILED(hr)) {
+              *error_message = "Failed to prepare delete operation";
+            }
+          }
+          else {
+            *error_message = "Failed to prepare delete operation";
+          }
+          psi->lpVtbl->Release(psi);
+        }
+        else {
+          *error_message = "Failed to parse path";
+        }
+      }
+      else {
+        *error_message = "Failed to set operation flags";
+      }
+      pfo->lpVtbl->Release(pfo);
+    }
+    else {
+      *error_message = "Failed to create FileOperation instance";
+    }
+    CoUninitialize();
   }
-
-  hr = pfo->lpVtbl->PerformOperations(pfo);
-
-  if (FAILED(hr)) {
-    *error_message = "Failed to delete file or directory";
+  else {
+    *error_message = "Failed to initialize COM";
   }
 
-error_2:
-  pfo->lpVtbl->Release(pfo);
-  CoUninitialize(); /* Has to be uninitialized when CoInitializeEx returns either S_OK or S_FALSE
-                     */
-error_1:
   return FAILED(hr);
 }



More information about the Bf-blender-cvs mailing list