[SHELL32][SDK] Implement CopyStreamUI (#5848)

- Modify shell32.spec.
- Add CopyStreamUI prototype to <undocshell.h>.
CORE-19278
This commit is contained in:
Katayama Hirofumi MZ 2023-10-31 22:32:02 +09:00 committed by GitHub
parent 60b0afc3af
commit 8a049d0b68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 126 additions and 12 deletions

View File

@ -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)

View File

@ -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
*/

View File

@ -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]
*

View File

@ -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
*/