From 83cb7864064fa6181902c28fc56d26f236881abe Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 10 Feb 2025 17:38:43 -0800 Subject: Support CreateFile with retries --- src/libs/dutil/WixToolset.DUtil/fileutil.cpp | 53 ++++++++++++++++++++++++-- src/libs/dutil/WixToolset.DUtil/inc/fileutil.h | 29 +++++++++----- 2 files changed, 69 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp index 31802d29..abe1f6ad 100644 --- a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp @@ -32,7 +32,7 @@ __out LPWSTR *ppwzFileNameNoExtension ) { Assert(wzFileName && *wzFileName); - + HRESULT hr = S_OK; size_t cchFileName = 0; LPWSTR pwzFileNameNoExtension = NULL; @@ -90,7 +90,7 @@ extern "C" HRESULT DAPI FileChangeExtension( LExit: ReleaseStr(sczFileName); - + return hr; } @@ -140,7 +140,7 @@ extern "C" HRESULT DAPI FileAddSuffixToBaseName( LExit: ReleaseStr(sczNewFileName); - + return hr; } @@ -1339,6 +1339,51 @@ LExit: } +/******************************************************************* + FileCreateWithRetry - create a file with multiple attempts if necessary + +********************************************************************/ +extern "C" HRESULT DAPI FileCreateWithRetry( + __in LPCWSTR wzFile, + __in DWORD dwDesiredAccess, + __in DWORD dwShareMode, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __in DWORD dwCreationDisposition, + __in DWORD dwFlagsAndAttributes, + __in DWORD cRetry, + __in DWORD dwWaitMilliseconds, + __out HANDLE* phFile + ) +{ + HRESULT hr = HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE); + + *phFile = INVALID_HANDLE_VALUE; + + for (DWORD i = 0; i <= cRetry; ++i) + { + if (0 < i) + { + ::Sleep(dwWaitMilliseconds); + } + + *phFile = ::CreateFileW(wzFile, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL); + if (INVALID_HANDLE_VALUE == *phFile) + { + DWORD er = ::GetLastError(); + hr = HRESULT_FROM_WIN32(er ? er : ERROR_INVALID_HANDLE); + } + else + { + hr = S_OK; + break; + } + } + FileExitOnRootFailure(hr, "Failed to create file: %ls after %u retries.", wzFile, cRetry); + +LExit: + return hr; +} + /******************************************************************* FileIsSame @@ -1479,7 +1524,7 @@ extern "C" HRESULT DAPI FileResetTime( hFile = ::CreateFileW(wzFile, FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); FileExitOnInvalidHandleWithLastError(hFile, hr, "Failed to open file. File = '%ls'", wzFile); - + if (!::GetFileTime(hFile, &ftCreateTime, NULL, NULL)) { FileExitWithLastError(hr, "Failed to get file time for file. File = '%ls'", wzFile); diff --git a/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h b/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h index 868312dc..c206fc5c 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/fileutil.h @@ -49,8 +49,8 @@ HRESULT DAPI FileAddSuffixToBaseName( __out_z LPWSTR* psczNewFileName ); HRESULT DAPI FileVersionFromString( - __in_z LPCWSTR wzVersion, - __out DWORD *pdwVerMajor, + __in_z LPCWSTR wzVersion, + __out DWORD *pdwVerMajor, __out DWORD* pdwVerMinor ); HRESULT DAPI FileVersionFromStringEx( @@ -73,11 +73,11 @@ HRESULT DAPI FileSize( __out LONGLONG* pllSize ); HRESULT DAPI FileSizeByHandle( - __in HANDLE hFile, + __in HANDLE hFile, __out LONGLONG* pllSize ); BOOL DAPI FileExistsEx( - __in_z LPCWSTR wzPath, + __in_z LPCWSTR wzPath, __out_opt DWORD *pdwAttributes ); BOOL DAPI FileExistsAfterRestart( @@ -166,8 +166,8 @@ HRESULT DAPI FileEnsureCopyWithRetry( __in DWORD dwWaitMilliseconds ); HRESULT DAPI FileEnsureMove( - __in_z LPCWSTR wzSource, - __in_z LPCWSTR wzTarget, + __in_z LPCWSTR wzSource, + __in_z LPCWSTR wzTarget, __in BOOL fOverwrite, __in BOOL fAllowCopy ); @@ -191,9 +191,20 @@ HRESULT DAPI FileCreateTempW( __deref_opt_out_z LPWSTR* ppwzTempFile, __out_opt HANDLE* phTempFile ); +HRESULT DAPI FileCreateWithRetry( + __in LPCWSTR wzFile, + __in DWORD dwDesiredAccess, + __in DWORD dwShareMode, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __in DWORD dwCreationDisposition, + __in DWORD dwFlagsAndAttributes, + __in DWORD cRetry, + __in DWORD dwWaitMilliseconds, + __out HANDLE* phFile + ); HRESULT DAPI FileVersion( - __in_z LPCWSTR wzFilename, - __out DWORD *pdwVerMajor, + __in_z LPCWSTR wzFilename, + __out DWORD *pdwVerMajor, __out DWORD* pdwVerMinor ); HRESULT DAPI FileIsSame( @@ -205,7 +216,7 @@ HRESULT DAPI FileEnsureDelete( __in_z LPCWSTR wzFile ); HRESULT DAPI FileGetTime( - __in_z LPCWSTR wzFile, + __in_z LPCWSTR wzFile, __out_opt LPFILETIME lpCreationTime, __out_opt LPFILETIME lpLastAccessTime, __out_opt LPFILETIME lpLastWriteTime -- cgit v1.2.3-55-g6feb