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