https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b6274fdde1670dff87fac2e6f1971b86d8b27d4f
commit b6274fdde1670dff87fac2e6f1971b86d8b27d4f Author: Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> AuthorDate: Mon Dec 18 12:37:50 2023 +0900 Commit: GitHub <nore...@github.com> CommitDate: Mon Dec 18 12:37:50 2023 +0900 [SHIMGVW] Unlock file (#6181) - Add m_pMemStream to PREVIEW_DATA structure. - Add Preview_pFreeImage helper function. - Add MemStreamFromFile helper function to make a memory stream. - Avoid file locking by using a memory stream and GdipLoadImageFromStream. CORE-19183 --- dll/win32/shimgvw/shimgvw.c | 97 ++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c index 0503449d87c..7cedfc1afde 100644 --- a/dll/win32/shimgvw/shimgvw.c +++ b/dll/win32/shimgvw/shimgvw.c @@ -105,6 +105,7 @@ typedef struct tagPREVIEW_DATA INT m_yScrollOffset; UINT m_nMouseDownMsg; POINT m_ptOrigin; + IStream *m_pMemStream; } PREVIEW_DATA, *PPREVIEW_DATA; static inline PPREVIEW_DATA @@ -328,7 +329,7 @@ Preview_UpdateTitle(PPREVIEW_DATA pData, LPCWSTR FileName) } static VOID -Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName) +Preview_pFreeImage(PPREVIEW_DATA pData) { Anime_FreeInfo(&pData->m_Anime); @@ -338,6 +339,51 @@ Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName) g_pImage = NULL; } + if (pData->m_pMemStream) + { + pData->m_pMemStream->lpVtbl->Release(pData->m_pMemStream); + pData->m_pMemStream = NULL; + } +} + +IStream* MemStreamFromFile(LPCWSTR pszFileName) +{ + HANDLE hFile; + DWORD dwFileSize, dwRead; + LPBYTE pbMemFile = NULL; + IStream *pStream; + + hFile = CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return NULL; + + dwFileSize = GetFileSize(hFile, NULL); + pbMemFile = QuickAlloc(dwFileSize, FALSE); + if (!dwFileSize || (dwFileSize == INVALID_FILE_SIZE) || !pbMemFile) + { + CloseHandle(hFile); + return NULL; + } + + if (!ReadFile(hFile, pbMemFile, dwFileSize, &dwRead, NULL) || (dwRead != dwFileSize)) + { + QuickFree(pbMemFile); + CloseHandle(hFile); + return NULL; + } + + CloseHandle(hFile); + pStream = SHCreateMemStream(pbMemFile, dwFileSize); + QuickFree(pbMemFile); + return pStream; +} + +static VOID +Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName) +{ + Preview_pFreeImage(pData); + /* check file presence */ if (!szOpenFileName || GetFileAttributesW(szOpenFileName) == 0xFFFFFFFF) { @@ -346,11 +392,21 @@ Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName) return; } - /* load now */ - GdipLoadImageFromFile(szOpenFileName, &g_pImage); + pData->m_pMemStream = MemStreamFromFile(szOpenFileName); + if (!pData->m_pMemStream) + { + DPRINT1("MemStreamFromFile() failed\n"); + Preview_UpdateTitle(pData, NULL); + return; + } + + /* NOTE: GdipLoadImageFromFile locks the file. + Avoid file locking by using GdipLoadImageFromStream and memory stream. */ + GdipLoadImageFromStream(pData->m_pMemStream, &g_pImage); if (!g_pImage) { - DPRINT1("GdipLoadImageFromFile() failed\n"); + DPRINT1("GdipLoadImageFromStream() failed\n"); + Preview_pFreeImage(pData); Preview_UpdateTitle(pData, NULL); return; } @@ -1221,21 +1277,12 @@ Preview_Delete(PPREVIEW_DATA pData) GetFullPathNameW(g_pCurrentFile->Next->FileName, _countof(szNextFile), szNextFile, NULL); szNextFile[_countof(szNextFile) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ - /* FIXME: Our GdipLoadImageFromFile locks the image file */ - if (g_pImage) - { - GdipDisposeImage(g_pImage); - g_pImage = NULL; - } - /* Confirm file deletion and delete if allowed */ FileOp.pFrom = szCurFile; FileOp.fFlags = FOF_ALLOWUNDO; if (SHFileOperationW(&FileOp) != 0) { DPRINT("Preview_Delete: SHFileOperationW() failed or canceled\n"); - - Preview_pLoadImage(pData, szCurFile); return; } @@ -1254,14 +1301,6 @@ Preview_Edit(HWND hwnd) if (!g_pCurrentFile) return; - /* Avoid file locking */ - /* FIXME: Our GdipLoadImageFromFile locks the image file */ - if (g_pImage) - { - GdipDisposeImage(g_pImage); - g_pImage = NULL; - } - GetFullPathNameW(g_pCurrentFile->FileName, _countof(szPathName), szPathName, NULL); szPathName[_countof(szPathName) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ @@ -1274,9 +1313,11 @@ Preview_Edit(HWND hwnd) { DPRINT1("Preview_Edit: ShellExecuteExW() failed with code %ld\n", GetLastError()); } - - // Destroy the window to quit the application - DestroyWindow(hwnd); + else + { + // Destroy the window to quit the application + DestroyWindow(hwnd); + } } static VOID @@ -1435,13 +1476,7 @@ Preview_OnDestroy(HWND hwnd) pFreeFileList(g_pCurrentFile); g_pCurrentFile = NULL; - if (g_pImage) - { - GdipDisposeImage(g_pImage); - g_pImage = NULL; - } - - Anime_FreeInfo(&pData->m_Anime); + Preview_pFreeImage(pData); SetWindowLongPtrW(pData->m_hwndZoom, GWLP_USERDATA, 0); DestroyWindow(pData->m_hwndZoom);