Wednesday, February 21, 2007 11:03 PM bart

Windows Vista - Introducing TxF in C# (part 3) - CreateFileTransacted demo

In November last year, I blogged about TxF:

A few days ago I received a mail from a reader of my blog who had an issue with a similar CreateFileTransacted code snippet which allows to manipulate file content in the scope of a transaction. In today's post, I show a little demo on how to do this.

1 using System; 2 using System.IO; 3 using Microsoft.Win32.SafeHandles; 4 using System.Runtime.InteropServices; 5 6 class TxfDemo 7 { 8 const uint GENERIC_READ = 0x80000000; 9 const uint GENERIC_WRITE = 0x40000000; 10 const uint CREATE_NEW = 1; 11 const uint CREATE_ALWAYS = 2; 12 const uint OPEN_EXISTING = 3; 13 14 [DllImport("kernel32.dll", SetLastError = true)] 15 static extern SafeFileHandle CreateFile( 16 string lpFileName, 17 uint dwDesiredAccess, 18 uint dwShareMode, 19 IntPtr lpSecurityAttributes, 20 uint dwCreationDisposition, 21 uint dwFlagsAndAttributes, 22 IntPtr hTemplateFile); 23 24 [DllImport("kernel32.dll", SetLastError = true)] 25 static extern SafeFileHandle CreateFileTransacted( 26 string lpFileName, 27 uint dwDesiredAccess, 28 uint dwShareMode, 29 IntPtr lpSecurityAttributes, 30 uint dwCreationDisposition, 31 uint dwFlagsAndAttributes, 32 IntPtr hTemplateFile, 33 IntPtr hTransaction, 34 IntPtr pusMiniVersion, 35 IntPtr pExtendedParameter); 36 37 [DllImport("ktmw32.dll", SetLastError = true)] 38 static extern IntPtr CreateTransaction( 39 IntPtr lpTransactionAttributes, 40 IntPtr uow, 41 uint createOptions, 42 uint isolationLevel, 43 uint isolationFlags, 44 uint timeout, 45 string description); 46 47 [DllImport("ktmw32.dll", SetLastError = true)] 48 static extern bool CommitTransaction( 49 IntPtr transaction); 50 51 [DllImport("ktmw32.dll", SetLastError = true)] 52 static extern bool RollbackTransaction( 53 IntPtr transaction); 54 55 [DllImport("Kernel32.dll")] 56 static extern bool CloseHandle(IntPtr handle); 57 58 static void Main() 59 { 60 string file = "txfdemo.txt"; 61 62 // 63 // For demo purposes, delete the file first (if it already exists). 64 // 65 if (File.Exists(file)) 66 File.Delete(file); 67 68 // 69 // Create KTM transaction. 70 // 71 IntPtr transaction = CreateTransaction(IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, null); 72 73 // 74 // Check transaction handle. 75 // 76 if (transaction == IntPtr.Zero) 77 { 78 Console.WriteLine("Oops! KTM has taken a day off."); 79 return; 80 } 81 82 try 83 { 84 // 85 // Non-transacted. 86 // 87 //SafeFileHandle handle = CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, CREATE_NEW, 0, IntPtr.Zero); 88 89 // 90 // Transacted file creation (CREATE_NEW). 91 // 92 SafeFileHandle handle = CreateFileTransacted(file, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, CREATE_NEW, 0, IntPtr.Zero, transaction, IntPtr.Zero, IntPtr.Zero); 93 94 // 95 // Check handle. 96 // 97 if (handle.IsInvalid) 98 Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error()); 99 100 // 101 // Using pattern for stream operations. 102 // 103 using (FileStream fs = new FileStream(handle,FileAccess.ReadWrite)) 104 { 105 using (StreamWriter sw = new StreamWriter(fs)) 106 { 107 sw.WriteLine("Hello"); 108 } 109 } 110 111 // 112 // To commit or not to commit? 113 // 114 Console.WriteLine("Press Y to commit"); 115 116 char c = Console.ReadKey().KeyChar; 117 if (c == 'y' || c == 'Y') 118 CommitTransaction(transaction); 119 else 120 RollbackTransaction(transaction); 121 } 122 catch (Exception ex) 123 { 124 Console.WriteLine("Oops! {0}", ex.Message); 125 126 // 127 // Rollback. 128 // 129 RollbackTransaction(transaction); 130 } 131 finally 132 { 133 // 134 // Close kernel mode transaction handle. 135 // 136 CloseHandle(tx); 137 } 138 } 139 }

The sample shows how to create a file (change CREATE_NEW on line 89 if you want to open an existing file for instance) and how to hand over the SafeFileHandle to the FileStream class for further usage. Notice that the code above has some fundamental security problems concerning path sanitation of the variable "file". You might want to take a look at the SSCLI code (\clr\src\bcl\system\io\filestream.cs - FileStream::Init(...) method) for details on how to implement a much safer library that calls CreateFile(Transacted). Especially, you have to pay attention to path normalization (do you really want ".." sequences in your path?), the infamous \\.\ sequence that allows to talk to ports (e.g. COM1), the \\?\ prefix for long path names (cf. MAX_PATH), code access security (cf. FileIOPermission demand), etc.

Ignoring the warnings above (which - one day - I might resolve using a TxF aware set of classes that incorporates the required security checks), the sample will create a file called "txfdemo.txt" in the current folder, write "Hello" to it (line 104) and wait for the end-user to press Y to commit. Before you press a key (line 113), open up an instance of Windows Explorer or another command prompt and observe that (due to the isolation property of ACID transactions) the file isn't present yet. If you press Y, the file will appear out of the blue because of the transaction commit. Any other key (other than 'y' and 'Y') will rollback the transaction, which also happens in case of an exception.

Exercise: (re)read Windows Vista - Introducing TxF in C# (part 2) - Using System.Transactions and the DTC and make the code above System.Transactions aware (also adding more flexibility concerning various parameters - line 89 - see Windows SDK CreateFileTransacted documentation for more info, as well as the .h header file that come with the SDK for symbolic constant values).

Brain.Commit();

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: , ,

Comments

# Kna??a emu??ri » Blog Archive » Da????di linki

Thursday, February 22, 2007 3:36 AM by Kna??a emu??ri » Blog Archive » Da????di linki

# Article Feed » Windows Vista - Introducing TxF in C# (part 3 …

# Vista internals - część 1. Zmiany w systemie plików

Monday, April 16, 2007 7:51 AM by mgrzeg.net - Admin on Rails :)

Windows Vista to najnowocześniejszy system operacyjny Microsoftu będący w sprzedaży. Od 2001 r., kiedy pojawił się Windows XP sporo się zmieniło i warto zapoznać się z nowościami. Tym wpisem otwieram krótką serię opisującą nowości w Viście i tego, jaki

# http://bartdesmet.net/blogs/bart/archive/2007/02/21/windows-vista-introducing-txf-in-c-part-3-createfiletransacted-demo.aspx

# How do I open a Windows 7 transacted file in C# - Programmers Goodies

Pingback from  How do I open a Windows 7 transacted file in C# - Programmers Goodies

# rimonabantexcellence site title

Sunday, July 21, 2013 9:01 AM by rimonabantexcellence site title

Pingback from  rimonabantexcellence site title