private static SafeFileHandle FindFirstFileTransacted(string dirSpec, KtmTransactionHandle ktmTx, out NativeMethods.WIN32_FIND_DATA findFileData) { SafeFileHandle hFile = NativeMethods.FindFirstFileTransacted( dirSpec, NativeMethods.FINDEX_INFO_LEVELS.FindExInfoStandard, out findFileData, NativeMethods.FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0, ktmTx); if (hFile.IsInvalid) { NativeMethods.HandleCOMError(Marshal.GetLastWin32Error()); } return(hFile); }
// TODO - BCL match - add overload that has a 'searchOption' argument public static FileSystemInfo[] GetFiles(string path, string searchPattern) { using (TransactionScope scope = new TransactionScope()) using (KtmTransactionHandle ktmTx = KtmTransactionHandle.CreateKtmTransactionHandle()) { string dirSpec = System.IO.Path.Combine(path, searchPattern); List<FileSystemInfo> files = new List<FileSystemInfo>(); List<FileSystemInfo> directories = new List<FileSystemInfo>(); NativeMethods.WIN32_FIND_DATA findFileData = new NativeMethods.WIN32_FIND_DATA(); SafeFileHandle hFind = FindFirstFileTransacted(dirSpec, ktmTx, out findFileData); try { // List all the other files in the directory. do { var fullPath = Path.Combine(path, findFileData.cFileName); if (0x10 == (0x10 & findFileData.dwFileAttributes)) { directories.Add(new DirectoryInfo(fullPath)); } else { var fileInfo = new FileInfo(fullPath); if (fileInfo.Exists) { var creationTime = findFileData.ftCreationTime.ToDateTime(); var lastAccessTime = findFileData.ftLastAccessTime.ToDateTime(); var lastWriteTime = findFileData.ftLastWriteTime.ToDateTime(); fileInfo.CreationTime = creationTime; fileInfo.LastAccessTime = lastAccessTime; fileInfo.LastWriteTime = lastWriteTime; } files.Add(fileInfo); } } while (NativeMethods.FindNextFile(hFind, out findFileData)); int error = Marshal.GetLastWin32Error(); if (error != NativeMethods.ERROR_NO_MORE_FILES) { NativeMethods.HandleCOMError(error); } scope.Complete(); directories.AddRange(files); return directories.ToArray(); } finally { // Ignore failures from this api just as the BCL does... NativeMethods.FindClose(hFind); hFind.SetHandleAsInvalid(); } } }