https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8a049d0b68ac18d4dfdaf4db3d3a2ef9bce2f607

commit 8a049d0b68ac18d4dfdaf4db3d3a2ef9bce2f607
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Tue Oct 31 22:32:02 2023 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Tue Oct 31 22:32:02 2023 +0900

    [SHELL32][SDK] Implement CopyStreamUI (#5848)
    
    - Modify shell32.spec.
    - Add CopyStreamUI prototype to <undocshell.h>.
    CORE-19278
---
 dll/win32/shell32/shell32.spec   |   2 +-
 dll/win32/shell32/stubs.cpp      |  11 ----
 dll/win32/shell32/utils.cpp      | 117 +++++++++++++++++++++++++++++++++++++++
 sdk/include/reactos/undocshell.h |   8 +++
 4 files changed, 126 insertions(+), 12 deletions(-)

diff --git a/dll/win32/shell32/shell32.spec b/dll/win32/shell32/shell32.spec
index dbdbfabd758..eb8685fe3c6 100644
--- a/dll/win32/shell32/shell32.spec
+++ b/dll/win32/shell32/shell32.spec
@@ -444,7 +444,7 @@
 723 stdcall -noname SHCreateSessionKey(long ptr)
 724 stdcall -noname SHIsTempDisplayMode()
 725 stdcall -noname GetFileDescriptor(ptr long long wstr)
-726 stdcall -noname CopyStreamUI(ptr ptr ptr)
+726 stdcall -noname CopyStreamUI(ptr ptr ptr int64)
 727 stdcall SHGetImageList(long ptr ptr)
 730 stdcall RestartDialogEx(long wstr long long)
 731 stdcall -noname -stub SHRegisterDarwinLink(long long long)
diff --git a/dll/win32/shell32/stubs.cpp b/dll/win32/shell32/stubs.cpp
index b1e153fdb67..91e8ae00beb 100644
--- a/dll/win32/shell32/stubs.cpp
+++ b/dll/win32/shell32/stubs.cpp
@@ -86,17 +86,6 @@ SHReValidateDarwinCache(VOID)
     FIXME("SHReValidateDarwinCache() stub\n");
 }
 
-/*
- * Unimplemented
- */
-EXTERN_C HRESULT
-WINAPI
-CopyStreamUI(IStream *pSrc, IStream *pDst, IProgressDialog *pProgDlg)
-{
-    FIXME("CopyStreamUI() stub\n");
-    return E_FAIL;
-}
-
 /*
  * Unimplemented
  */
diff --git a/dll/win32/shell32/utils.cpp b/dll/win32/shell32/utils.cpp
index 697a4f59cea..1e7cfbe28ac 100644
--- a/dll/win32/shell32/utils.cpp
+++ b/dll/win32/shell32/utils.cpp
@@ -540,6 +540,123 @@ LargeIntegerToString(
                          pNumberFormat, dwNumberFlags);
 }
 
+/*************************************************************************
+ *  CopyStreamUI [SHELL32.726]
+ *
+ * Copy a stream to another stream with optional progress display.
+ */
+EXTERN_C
+HRESULT WINAPI
+CopyStreamUI(
+    _In_ IStream *pSrc,
+    _Out_ IStream *pDst,
+    _Inout_opt_ IProgressDialog *pProgress,
+    _In_opt_ DWORDLONG dwlSize)
+{
+    HRESULT hr = E_FAIL;
+    DWORD cbBuff, cbRead, dwSizeToWrite;
+    DWORDLONG cbDone;
+    LPVOID pBuff;
+    CComHeapPtr<BYTE> pHeapPtr;
+    STATSTG Stat;
+    BYTE abBuff[1024];
+
+    TRACE("(%p, %p, %p, %I64u)\n", pSrc, pDst, pProgress, dwlSize);
+
+    if (dwlSize == 0) // Invalid size?
+    {
+        // Get the stream size
+        ZeroMemory(&Stat, sizeof(Stat));
+        if (FAILED(pSrc->Stat(&Stat, STATFLAG_NONAME)))
+            pProgress = NULL; // No size info. Disable progress
+        else
+            dwlSize = Stat.cbSize.QuadPart;
+    }
+
+    if (!pProgress) // Progress is disabled?
+    {
+        ULARGE_INTEGER uliSize;
+
+        if (dwlSize > 0)
+            uliSize.QuadPart = dwlSize;
+        else
+            uliSize.HighPart = uliSize.LowPart = INVALID_FILE_SIZE;
+
+        return pSrc->CopyTo(pDst, uliSize, NULL, NULL); // One punch
+    }
+
+    // Allocate the buffer if necessary
+    if (dwlSize > 0 && dwlSize <= sizeof(abBuff))
+    {
+        cbBuff = sizeof(abBuff);
+        pBuff = abBuff;
+    }
+    else
+    {
+#define COPY_STREAM_DEFAULT_BUFFER_SIZE 0x4000
+        cbBuff = COPY_STREAM_DEFAULT_BUFFER_SIZE;
+        if (pHeapPtr.AllocateBytes(cbBuff))
+        {
+            pBuff = pHeapPtr;
+        }
+        else // Low memory?
+        {
+            cbBuff = sizeof(abBuff);
+            pBuff = abBuff;
+        }
+#undef COPY_STREAM_DEFAULT_BUFFER_SIZE
+    }
+
+    // Start reading
+    LARGE_INTEGER zero;
+    zero.QuadPart = 0;
+    pSrc->Seek(zero, 0, NULL);
+    pDst->Seek(zero, 0, NULL);
+    cbDone = 0;
+    pProgress->SetProgress64(cbDone, dwlSize);
+
+    // Repeat reading and writing until goal
+    for (;;)
+    {
+        hr = pSrc->Read(pBuff, cbBuff, &cbRead);
+        if (FAILED(hr))
+            break;
+
+        // Calculate the size to write
+        if (dwlSize > 0)
+            dwSizeToWrite = (DWORD)min((DWORDLONG)(dwlSize - cbDone), 
(DWORDLONG)cbRead);
+        else
+            dwSizeToWrite = cbRead;
+
+        if (dwSizeToWrite == 0) // No need to write?
+        {
+            hr = S_OK;
+            break;
+        }
+
+        hr = pDst->Write(pBuff, dwSizeToWrite, NULL);
+        if (hr != S_OK)
+            break;
+
+        cbDone += dwSizeToWrite;
+
+        if (pProgress->HasUserCancelled()) // Cancelled?
+        {
+            hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
+            break;
+        }
+        pProgress->SetProgress64(cbDone, dwlSize);
+
+        if (dwlSize > 0 && cbDone >= dwlSize) // Reached the goal?
+        {
+            hr = S_OK;
+            break;
+        }
+    }
+
+    return hr;
+}
+
 /*************************************************************************
  *  SHOpenPropSheetA [SHELL32.707]
  *
diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h
index 95cc7b6998b..8fad6faa6a8 100644
--- a/sdk/include/reactos/undocshell.h
+++ b/sdk/include/reactos/undocshell.h
@@ -817,6 +817,14 @@ LONG WINAPI SHRegQueryValueExW(
     #define SHRegQueryValueEx SHRegQueryValueExA
 #endif
 
+EXTERN_C
+HRESULT WINAPI
+CopyStreamUI(
+    _In_ IStream *pSrc,
+    _Out_ IStream *pDst,
+    _Inout_opt_ IProgressDialog *pProgress,
+    _In_opt_ DWORDLONG dwlSize);
+
 /*****************************************************************************
  * INVALID_FILETITLE_CHARACTERS
  */

Reply via email to