https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b6274fdde1670dff87fac2...
commit b6274fdde1670dff87fac2e6f1971b86d8b27d4f Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Mon Dec 18 12:37:50 2023 +0900 Commit: GitHub noreply@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);