[Undelete Logo] Copyright © 1997-1998 Mark Russinovich and Bryce Cogswell Last Updated October 3, 1998 Version 2.0 ------------------------------------------------------------------------ Introduction Although NT 4.0 provides a Recycle Bin, it is of very limited use. Only files deleted from the Explorer GUI end up being placed there. Any files zapped from a command window or from within a program are lost forever. Undelete is a utility that replaces NT 4.0's Recycle Bin to provide full protection of files deleted from anywhere. Undelete includes the same configurability as Recycle Bin's Properties dialog, including which drives should have protection enabled, and how large the Undelete Bin should be allowed to grow. Undelete also provides a filtering dialog that allows you to prevent files of specific extensions not to be sent to the Bin, such as editor backup files, and temporary files. You can also specify directories that will be excluded from protection. Installation Undelete is installed with a self-extracting install and Use program. No file extension filters are automatically installed, so after installation you might want to run the Undelete filter dialog (placed in the Undelete program group) and add to it extensions and directories that you want undelete support disabled for. After rebooting, any files you delete from within programs or the command prompt , which are not being filtered from protection, will be moved to the Recycle Bin. Simply use the Undelete Bin as you would for files deleted from Explorer to recover deleted files. The Source Code The full source code to Undelete is provided for educational purposes. There are a few aspect of the Undelete device driver, which is a file system filter driver, that will be interesting to device driver developers. Some of the techniques and demonstrated by the code include: * An MFC Recycle Bin clone that demonstrates full-row selection listview controls. * Synchronizing access to a file that is accessed from a GUI and a driver. The Undelete GUI passes a mutex handle to the driver, which obtains a mutex object pointer from it. Thereafter the GUI and driver can access the Undelete Bin files without interfering with each other through the use of the shared mutex. * Enumerating the contents of a directory from within a driver. Undelete must honor the Recycle Bin's size setting so it must dynamically calculate the size of a Bin (the size of all the files it contains). * How a filter driver can both stall IRPs headed to a file system, and create and dispatch new IRPs before completing an original request. This highlights the use of STATUS_PENDING and STATUS_MORE_PROCESSING_REQUIRED as return codes. * Dynamically determining the SID of a user from within its driver when Undelete must store a file in a NTFS recycle bin. Obtaining the One technique that is of particular interest for Current SID in developers is Undelete's method for determining the a Driver SID of the user that is performing a file system operation. This is acommplished in several steps. First, Undelete references the current access token, obtaining a pointer to its object body: completeContext->Token = PsReferencePrimaryToken(PsGetCurrentProcess()); The next step is for it to obtain a handle to the token object, because token query operations are handle-based. Undelete accomplishes this through the use of an undocumented API, ObOpenObjectByPointer, that will take an object and create a handle for it in the currently executing process: ntStatus = ObOpenObjectByPointer( CompleteContext->Token, 0, NULL, TOKEN_QUERY, NULL, KernelMode, &tokenHandle ); ObDereferenceObject( CompleteContext->Token ); After the handle is returned Undelete can query the token using the NtQueryInformationToken native API. This function is the basis for the Win32-equivalent, GetInformationToken, so determining its parameters and their formats is straight-forward. Definitions from the Win32 header files are included in Undelete's header so that Undelete can perform a TokenUser query on the token, which returns the token's user information including the SID. tokenInfoBuffer = (PTOKEN_USER) ExAllocatePool( NonPagedPool, requiredLength ); ntStatus = NtQueryInformationToken( tokenHandle, TokenUser, tokenInfoBuffer, requiredLength, &requiredLength ); ZwClose( tokenHandle ); The final step Undelete performs is to convert the binary representation of the SID into a textual representation. Another undocumented API, RtlConvertSidToUnicodeString, performs this. memset( sidStringBuffer, 0, sizeof(sidStringBuffer )); sidString.Buffer = (PWCHAR) sidStringBuffer; sidString.MaximumLength = sizeof(sidStringBuffer); ntStatus = RtlConvertSidToUnicodeString( &sidString, tokenInfoBuffer->User.Sid, FALSE ); ------------------------------------------------------------------------ Download Undelete (894KB) Download Undelete Source Code (370KB) [Image]