#include <windows.h>#include <ktmw32.h>#include <stdio.h>#include <stdlib.h>#include <tchar.h>int __cdecl _tmain(int argc, TCHAR ** argv){ HANDLE hTrans; STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInformation; SECURITY_ATTRIBUTES saSecurityAttributes; if (argc<2) { _tprintf(_T("Usage: %s <appname>\n"), argv[0]); return EXIT_FAILURE; } // Clear out the structure memset (&saSecurityAttributes, 0, sizeof(saSecurityAttributes)); // Make the transaction inheritable, so child processes can use it. saSecurityAttributes.bInheritHandle = TRUE; // Create the transaction. hTrans = CreateTransaction(&saSecurityAttributes, NULL, 0, 0, 0, 0, NULL); if (hTrans == INVALID_HANDLE_VALUE) { _tprintf(_T("Could not create transaction.\n")); return EXIT_FAILURE; } // Currently, we're still operating as a normal, non-transacted // thread. To use the transaction we've just created, call // SetCurrentTransaction. if (!SetCurrentTransaction(hTrans)) { _tprintf(_T("Could not change transactions.\n")); return EXIT_FAILURE; } memset(&siStartupInfo, 0, sizeof(siStartupInfo)); siStartupInfo.cb = sizeof(siStartupInfo); // Start a child process, inheriting the transaction. Anything // you do from this process will now be transactional! Neat, huh? if (!CreateProcess(NULL, argv[1], NULL, NULL, TRUE, // Inherit transaction handle! NORMAL_PRIORITY_CLASS, NULL, NULL, &siStartupInfo, &piProcessInformation)) { _tprintf(_T("Could not run %s, GetLastError returns %i.\n"), argv[1], GetLastError()); return EXIT_FAILURE; } // Wait for the child process to finish. This is really // important, because we don't want to commit the transaction // until the child process isn't using it anymore. WaitForSingleObject(piProcessInformation.hProcess, INFINITE); CloseHandle(piProcessInformation.hThread); CloseHandle(piProcessInformation.hProcess); // All of a sudden, changes the child process made to the // filesystem become atomically visible to everybody else :) if (!CommitTransaction(hTrans)) { _tprintf(_T("Could not commit the transaction.\n")); return EXIT_FAILURE; } // We're still running transactionally, but that transaction // has just been committed. Any other file-based operations // would fail now. So let's switch back to the normal, // boring, non-transacted state. if (!SetCurrentTransaction(NULL)) { _tprintf(_T("Could not switch back to non-transactional state.\n")); return EXIT_FAILURE; } // A transaction handle still needs to be closed, like everything // else. CloseHandle(hTrans); return EXIT_SUCCESS;}
N:\temp>dir Volume in drive N is New Volume Volume Serial Number is EE91-9028 Directory of N:\temp04/25/2005 12:57 PM <DIR> .04/25/2005 12:57 PM <DIR> ..04/22/2005 02:01 PM 4,608 test.exe 1 File(s) 4,608 bytes 2 Dir(s) 3,081,523,200 bytes freeN:\temp>test cmdMicrosoft Windows [Version 6.0.5061](C) Copyright 1985-2005 Microsoft Corp.N:\temp>echo foobar>fileN:\temp>dir Volume in drive N is New Volume Volume Serial Number is EE91-9028 Directory of N:\temp04/25/2005 12:58 PM <DIR> .04/25/2005 12:58 PM <DIR> ..04/25/2005 12:58 PM 8 file04/22/2005 02:01 PM 4,608 test.exe 2 File(s) 4,616 bytes 2 Dir(s) 3,081,523,200 bytes freeN:\temp>exitN:\temp>dir Volume in drive N is New Volume Volume Serial Number is EE91-9028 Directory of N:\temp04/25/2005 12:58 PM <DIR> .04/25/2005 12:58 PM <DIR> ..04/25/2005 12:58 PM 8 file04/22/2005 02:01 PM 4,608 test.exe 2 File(s) 4,616 bytes 2 Dir(s) 3,081,523,200 bytes freeN:\temp>
N:\temp>dir Volume in drive N is New Volume Volume Serial Number is EE91-9028 Directory of N:\temp04/25/2005 12:57 PM <DIR> .04/25/2005 12:57 PM <DIR> ..04/22/2005 02:01 PM 4,608 test.exe 1 File(s) 4,608 bytes 2 Dir(s) 3,081,523,200 bytes freeN:\temp>dir Volume in drive N is New Volume Volume Serial Number is EE91-9028 Directory of N:\temp04/25/2005 12:58 PM <DIR> .04/25/2005 12:58 PM <DIR> ..04/22/2005 02:01 PM 4,608 test.exe 1 File(s) 4,608 bytes 2 Dir(s) 3,081,523,200 bytes freeN:\temp>dir Volume in drive N is New Volume Volume Serial Number is EE91-9028 Directory of N:\temp04/25/2005 12:58 PM <DIR> .04/25/2005 12:58 PM <DIR> ..04/25/2005 12:58 PM 8 file04/22/2005 02:01 PM 4,608 test.exe 2 File(s) 4,616 bytes 2 Dir(s) 3,081,523,200 bytes freeN:\temp>