www.pudn.com > NTFSUndelete_src.zip > UndeleteDlg.cpp


// UndeleteDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "Undelete.h" 
#include "UndeleteDlg.h" 
#include "FindDlg.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define PHYSICAL_DRIVE "\\\\.\\PhysicalDrive0" 
 
int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)  
{ 
	switch(uMsg)  
	{ 
	case BFFM_INITIALIZED:  
		SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData); 
		break; 
	default: 
		break; 
	} 
	return 0; 
} 
 
BOOL GetDirectory(HWND hWnd, LPTSTR szDir, LPTSTR szDefaultPath)  
{  
	BOOL			fRet;  
	TCHAR			szPath[MAX_PATH];  
	LPITEMIDLIST	pidl;  
	LPMALLOC		lpMalloc;   
	BROWSEINFO		bi = {hWnd, NULL, szPath, " Please select a folder to extract ", BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE, NULL, 0L, 0}; 
 
 
	if(szDefaultPath) 
	{ 
		bi.lpfn = BrowseCallbackProc; 
		bi.lParam = (LPARAM)szDefaultPath; 
	} 
 
	pidl = SHBrowseForFolder(&bi);   
	if (NULL != pidl)  
		fRet = SHGetPathFromIDList(pidl, szDir);  
	else  
		fRet = FALSE;  
	// Get the shell's allocator to free PIDLs  
	if(!SHGetMalloc(&lpMalloc) && (NULL != lpMalloc))  
	{  
		if(NULL != pidl)  
		{  
			lpMalloc->Free(pidl);  
		}   
		lpMalloc->Release();  
	}   
	return fRet;  
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	//{{AFX_MSG(CAboutDlg) 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
	//{{AFX_DATA_INIT(CAboutDlg) 
	//}}AFX_DATA_INIT 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAboutDlg) 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
		// No message handlers 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CUndeleteDlg dialog 
 
CUndeleteDlg::CUndeleteDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CUndeleteDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CUndeleteDlg) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 
 
void CUndeleteDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CUndeleteDlg) 
		// NOTE: the ClassWizard will add DDX and DDV calls here 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CUndeleteDlg, CDialog) 
	//{{AFX_MSG_MAP(CUndeleteDlg) 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_BN_CLICKED(IDC_BTNSCAN, OnBtnScan) 
	ON_WM_DESTROY() 
	ON_COMMAND(ID_MNU_FIND_FIRST, OnMnuFindFirst) 
	ON_COMMAND(ID_MNU_FIND_NEXT, OnMnuFindNext) 
	ON_COMMAND(ID_MNU_SAVE, OnMnuSave) 
	ON_NOTIFY(NM_RCLICK, IDC_LSTFILES, OnRClickLstFiles) 
	ON_NOTIFY(LVN_KEYDOWN, IDC_LSTFILES, OnKeyDownLstFiles) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CUndeleteDlg message handlers 
 
BOOL CUndeleteDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
	ASSERT(IDM_ABOUTBOX < 0xF000); 
 
	CMenu* pSysMenu = GetSystemMenu(FALSE); 
	if (pSysMenu != NULL) 
	{ 
		CString strAboutMenu; 
		strAboutMenu.LoadString(IDS_ABOUTBOX); 
		if (!strAboutMenu.IsEmpty()) 
		{ 
			pSysMenu->AppendMenu(MF_SEPARATOR); 
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
		} 
	} 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
 
	m_hDrive = INVALID_HANDLE_VALUE; 
	 
	CListCtrl *pList = (CListCtrl*)GetDlgItem(IDC_LSTFILES); 
	 
	pList->InsertColumn(0,"Filename",LVCFMT_CENTER,190,0); 
	pList->InsertColumn(1,"#",LVCFMT_CENTER,60,0); 
	pList->InsertColumn(2,"Attribute",LVCFMT_CENTER,80,0); 
	pList->InsertColumn(3,"Clusters",LVCFMT_CENTER,70,0); 
	pList->InsertColumn(3,"Deleted",LVCFMT_CENTER,50,0); 
	 
	pList->SetExtendedStyle(LVS_EX_FULLROWSELECT); 
 
	int nArr[] = {1,0,2,3,4}; 
 
	pList->SetColumnOrderArray(5,nArr); 
 
 
	m_hTreeRoot = ((CTreeCtrl*)GetDlgItem(IDC_TREDISKS))->InsertItem("Drives", 0, 0, TVI_ROOT, TVI_LAST); 
 
	void *lpMsgBuf; 
	int nRet = ScanLogicalDrives(); 
	if(nRet) 
	{ 
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,nRet, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
		MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
		LocalFree(lpMsgBuf); 
	} 
 
	m_bStopScanFilesThread = true; 
	m_hScanFilesThread = NULL; 
	 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CUndeleteDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
void CUndeleteDlg::OnDestroy()  
{ 
	if(m_hDrive != INVALID_HANDLE_VALUE) 
		CloseHandle(m_hDrive); 
 
	m_hDrive = INVALID_HANDLE_VALUE; 
 
	CDialog::OnDestroy(); 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CUndeleteDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CUndeleteDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
void CUndeleteDlg::AddDrive(char *szDrvTxt, DRIVEPACKET *pstDrive) 
{ 
	DRIVEPACKET *pDrive = new DRIVEPACKET; 
 
	memcpy(pDrive,pstDrive, sizeof(DRIVEPACKET)); 
 
	((CTreeCtrl*)GetDlgItem(IDC_TREDISKS))->InsertItem(TVIF_TEXT|TVIF_PARAM, szDrvTxt, 0, 0, 0, 0, (LPARAM)pDrive, m_hTreeRoot, TVI_LAST); 
} 
 
/// This function is from vinoj kumar's article forensic in codeguru 
//    btw, it was a messy code  I have modified it left & right  
int CUndeleteDlg::ScanLogicalDrives() 
{ 
	int i,nRet; 
	DWORD dwBytes; 
 
	PARTITION *PartitionTbl; 
	DRIVEPACKET stDrive; 
 
	BYTE szSector[512]; 
	WORD wDrive =0; 
 
	char szTmpStr[64]; 
	char szTxt[255]; 
	 
	DWORD dwMainPrevRelSector =0; 
	DWORD dwPrevRelSector =0; 
 
	HANDLE hDrive = CreateFile(PHYSICAL_DRIVE,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); 
	if(hDrive == INVALID_HANDLE_VALUE) 
		return GetLastError(); 
 
	nRet = ReadFile(hDrive,szSector,512,&dwBytes,0); 
	if(!nRet) 
		return GetLastError(); 
 
	dwPrevRelSector =0; 
	dwMainPrevRelSector =0; 
 
	PartitionTbl = (PARTITION*)(szSector+0x1BE); 
 
	for(i=0; i<4; i++) /// scanning partitions in the physical disk 
	{ 
		stDrive.wCylinder = PartitionTbl->chCylinder; 
		stDrive.wHead = PartitionTbl->chHead; 
		stDrive.wSector = PartitionTbl->chSector; 
		stDrive.dwNumSectors = PartitionTbl->dwNumberSectors; 
		stDrive.wType = ((PartitionTbl->chType == PART_EXTENDED) || (PartitionTbl->chType == PART_DOSX13X)) ? EXTENDED_PART:BOOT_RECORD; 
 
		if((PartitionTbl->chType == PART_EXTENDED) || (PartitionTbl->chType == PART_DOSX13X)) 
		{ 
			dwMainPrevRelSector			= PartitionTbl->dwRelativeSector; 
			stDrive.dwNTRelativeSector	= dwMainPrevRelSector; 
		} 
		else 
		{ 
			stDrive.dwNTRelativeSector = dwMainPrevRelSector + PartitionTbl->dwRelativeSector; 
		} 
 
		if(stDrive.wType == EXTENDED_PART) 
			break; 
 
		if(PartitionTbl->chType == 0) 
			break; 
 
		switch(PartitionTbl->chType) 
		{ 
		case PART_DOS2_FAT: 
			strcpy(szTmpStr, "FAT12"); 
			break; 
		case PART_DOSX13: 
		case PART_DOS4_FAT: 
		case PART_DOS3_FAT: 
			strcpy(szTmpStr, "FAT16"); 
			break; 
		case PART_DOS32X: 
		case PART_DOS32: 
			strcpy(szTmpStr, "FAT32");			//Normal FAT32 
			break; 
		case 7: 
			strcpy(szTmpStr, "NTFS");	// NTFS , v r interested only on this 
			break; 
		default: 
			strcpy(szTmpStr, "Unknown"); 
			break; 
		} 
 
		wsprintf(szTxt, "%s Drive %d", szTmpStr,wDrive); 
 
		AddDrive(szTxt,&stDrive); 
		PartitionTbl++; 
		wDrive++; 
	} 
 
	if(i==4) 
		return ERROR_SUCCESS; 
 
	for(int LogiHard=0; LogiHard<50; LogiHard++) // scanning extended partitions 
	{ 
		if(stDrive.wType == EXTENDED_PART) 
		{ 
			LARGE_INTEGER n64Pos; 
 
			n64Pos.QuadPart = ((LONGLONG) stDrive.dwNTRelativeSector) * 512; 
			 
			nRet = SetFilePointer(hDrive, n64Pos.LowPart,&n64Pos.HighPart, FILE_BEGIN); 
			if(nRet == 0xffffffff) 
				return GetLastError();; 
 
			dwBytes = 0; 
 
			nRet = ReadFile(hDrive, szSector, 512, (DWORD *) &dwBytes, NULL); 
			if(!nRet) 
				return GetLastError(); 
 
			if(dwBytes != 512) 
				return ERROR_READ_FAULT; 
			 
			PartitionTbl = (PARTITION *) (szSector+0x1BE); 
 
			for(i=0; i<4; i++) 
			{ 
				stDrive.wCylinder = PartitionTbl->chCylinder; 
				stDrive.wHead = PartitionTbl->chHead; 
				stDrive.dwNumSectors = PartitionTbl->dwNumberSectors; 
				stDrive.wSector = PartitionTbl->chSector; 
				stDrive.dwRelativeSector = 0; 
				stDrive.wType = ((PartitionTbl->chType == PART_EXTENDED) || (PartitionTbl->chType == PART_DOSX13X)) ? EXTENDED_PART:BOOT_RECORD; 
				 
				if((PartitionTbl->chType == PART_EXTENDED) || (PartitionTbl->chType == PART_DOSX13X)) 
				{ 
					dwPrevRelSector = PartitionTbl->dwRelativeSector; 
					stDrive.dwNTRelativeSector = dwPrevRelSector + dwMainPrevRelSector; 
				} 
				else 
				{ 
					stDrive.dwNTRelativeSector = dwMainPrevRelSector + dwPrevRelSector + PartitionTbl->dwRelativeSector; 
				} 
 
				if(stDrive.wType == EXTENDED_PART) 
					break; 
 
				if(PartitionTbl->chType == 0) 
					break; 
 
				switch(PartitionTbl->chType) 
				{ 
				case PART_DOS2_FAT: 
					strcpy(szTmpStr, "FAT12"); 
					break; 
				case PART_DOSX13: 
				case PART_DOS4_FAT: 
				case PART_DOS3_FAT: 
					strcpy(szTmpStr, "FAT16"); 
					break; 
				case PART_DOS32X: 
				case PART_DOS32: 
					strcpy(szTmpStr, "FAT32");			//Normal FAT32 
					break; 
				case 7: 
					strcpy(szTmpStr, "NTFS"); 
					break; 
				default: 
					strcpy(szTmpStr, "Unknown"); 
					break; 
				} 
				wsprintf(szTxt, "%s Drive %d", szTmpStr, wDrive); 
				AddDrive(szTxt,&stDrive); 
				PartitionTbl++; 
				wDrive++; 
			} 
			if(i==4) 
				break; 
		} 
	} 
 
	CloseHandle(hDrive); 
	return ERROR_SUCCESS; 
} 
 
void CUndeleteDlg::OnBtnScan()  
{ 
	DWORD dwCode; 
	CString cszTxt; 
 
	GetDlgItemText(IDC_BTNSCAN,cszTxt); 
 
	if(cszTxt == "Scan Files") 
	{ 
		m_bStopScanFilesThread = false; 
		m_hScanFilesThread = CreateThread(NULL,0,ScanFilesThread,this,0,0); 
 
		SetDlgItemText(IDC_BTNSCAN,"Stop Scanning"); 
	} 
	else 
	{ 
		m_bStopScanFilesThread = true; 
		 
		dwCode = 0; 
		if(GetExitCodeThread(m_hScanFilesThread,&dwCode))// make sure the thread is exited 
		{ 
			if(dwCode == STILL_ACTIVE) 
			{ 
				SetDlgItemText(IDC_BTNSCAN,"Stopping..."); 
				GetDlgItem(IDC_BTNSCAN)->EnableWindow(false); 
				return; 
			} 
		} 
		 
		SetDlgItemText(IDC_BTNSCAN,"Scan Files");	 
		CloseHandle(m_hScanFilesThread); 
		m_hScanFilesThread = NULL; 
	} 
} 
 
void CUndeleteDlg::OnRClickLstFiles(NMHDR* pNMHDR, LRESULT* pResult)  
{ // right clicking feature 
	CMenu cMnu; 
	cMnu.LoadMenu(IDR_MNULSTFILES); 
	CMenu* pPopup = cMnu.GetSubMenu(0); 
 
	DWORD dwPos = GetMessagePos(); 
	CPoint cPt; 
	cPt.x = (int)LOWORD (dwPos); 
	cPt.y = (int) HIWORD (dwPos); 
  
	int nID = pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD,cPt.x,cPt.y,this,NULL); 
	if(nID == ID_MNU_FIND_FIRST) 
	{ 
		OnMnuFindFirst(); 
	} 
	else if(nID == ID_MNU_FIND_NEXT) 
	{ 
		OnMnuFindNext(); 
	} 
	else if(nID == ID_MNU_SAVE) 
	{ 
		OnMnuSave(); 
		 
	} 
	*pResult = 0; 
} 
 
void CUndeleteDlg::OnMnuFindFirst()  
{ 
	CFindDlg cFindDlg; 
	CString cszTxt; 
	DWORD i,dwCount; 
 
	CListCtrl *pcList = (CListCtrl*)GetDlgItem(IDC_LSTFILES); 
	dwCount = pcList->GetItemCount(); 
 
	cFindDlg.m_cszFindText = m_cszFindText;	 
 
	if(cFindDlg.DoModal() == IDCANCEL) 
		return; 
 
	m_cszFindText = cFindDlg.m_cszFindText; 
	 
	if(m_cszFindText == "") 
		return; 
 
	for(i=0;iGetItemText(i,0); 
		 
		cszTxt.TrimRight(); 
		if(cszTxt == "") 
			continue; 
 
		cszTxt.MakeLower(); 
		m_cszFindText.MakeLower(); 
 
		if(cszTxt.Find(m_cszFindText) >=0)  
		{// string found 
			pcList->EnsureVisible(i,false); 
			pcList->SetItemState(i,LVIS_SELECTED,0x0000000f); 
			m_dwFoundItem = i; 
			break; 
		} 
	} 
} 
 
void CUndeleteDlg::OnMnuFindNext()  
{ 
	CString cszTxt; 
	DWORD i,dwCount; 
 
	CListCtrl *pcList = (CListCtrl*)GetDlgItem(IDC_LSTFILES); 
	dwCount = pcList->GetItemCount(); 
 
	if(m_cszFindText == "") 
		return; 
 
	m_dwFoundItem++; 
	if(m_dwFoundItem > dwCount) 
	{ 
		MessageBox("Reached the end of list"); 
		m_dwFoundItem = 0; 
		return; 
	} 
 
	for(i=m_dwFoundItem;iGetItemText(i,0); 
 
		cszTxt.TrimRight(); 
		if(cszTxt == "") 
			continue; 
		 
		cszTxt.MakeLower(); 
		m_cszFindText.MakeLower(); 
 
		if(cszTxt.Find(m_cszFindText) >=0)  
		{// string found 
			pcList->EnsureVisible(i,false); 
			pcList->SetItemState(i,LVIS_SELECTED,0x0000000f); 
			m_dwFoundItem = i; 
			break; 
		} 
	} 
	if(i==dwCount) 
	{ 
		MessageBox("Reached the end of list"); 
		m_dwFoundItem = 0; 
	} 
} 
 
 
void CUndeleteDlg::OnMnuSave()  
{// saving tyhe files , saving the deleted & present files 
	CListCtrl *pcList = (CListCtrl*)GetDlgItem(IDC_LSTFILES); 
 
	char szPath[_MAX_PATH]; 
	char szTmpPath[_MAX_PATH]; 
	char szBuff[32]; 
	int nIdxSelLst; 
	int nRet; 
	void *lpMsgBuf; 
	BYTE *pData; 
	DWORD dwBytes =0; 
	DWORD dwLen; 
 
	CNTFSDrive::ST_FILEINFO stFInfo; 
 
	POSITION pos = pcList->GetFirstSelectedItemPosition(); 
	if(!pos) 
		return; 
 
	GetCurrentDirectory(_MAX_PATH,szPath); 
	if(!GetDirectory(this->m_hWnd, szPath,szPath)) 
		return; 
 
	BeginWaitCursor(); 
	while(pos) 
	{ 
		strcpy(szTmpPath,szPath); 
 
		nIdxSelLst = pcList->GetNextSelectedItem(pos); 
		pcList->GetItemText(nIdxSelLst,1,szBuff,32); 
		 
		nIdxSelLst = atol(szBuff); 
 
		nRet = m_cNTFS.Read_File(nIdxSelLst+30,pData,dwLen); // read the file content in to a buffer 
		if(nRet)                      
		{ 
			EndWaitCursor(); 
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,nRet, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
			MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
			LocalFree(lpMsgBuf); 
			return; 
		} 
 
		nRet = m_cNTFS.GetFileDetail(nIdxSelLst+30,stFInfo); // not get the file detail for FileName 
		if(nRet) 
		{ 
			EndWaitCursor(); 
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,nRet, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
			MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
			LocalFree(lpMsgBuf);; 
			return; 
		} 
 
		strcat(szTmpPath,"\\"); 
		strcat(szTmpPath,stFInfo.szFilename); 
 
		/// create the new file and save the contents 
		HANDLE hNewFile = CreateFile(szTmpPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,stFInfo.dwAttributes,0); 
		if(hNewFile == INVALID_HANDLE_VALUE) 
		{ 
			EndWaitCursor(); 
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
			MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
			LocalFree(lpMsgBuf); 
			return; 
		} 
		 
		nRet = WriteFile(hNewFile,pData,dwLen,&dwBytes,NULL); 
		if(!nRet) 
		{ 
			EndWaitCursor(); 
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
			MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
			LocalFree(lpMsgBuf); 
			return; 
		} 
		delete pData; 
		CloseHandle(hNewFile); 
	} 
} 
 
// F3 ...find next feature 
void CUndeleteDlg::OnKeyDownLstFiles(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR; 
	 
	if(pLVKeyDow->wVKey == VK_F3) 
	{ 
		OnMnuFindNext(); 
	}	 
	*pResult = 0; 
} 
 
 
DWORD WINAPI CUndeleteDlg::ScanFilesThread(LPVOID lpVoid) 
{ 
	CUndeleteDlg *pDlg = (CUndeleteDlg *)lpVoid; 
 
	DRIVEPACKET *pDrive;	 
	CNTFSDrive::ST_FILEINFO stFInfo; 
	char szBuffer[255]; 
	DWORD dwDeleted = 0, dwBytes =0, i; 
	int nRet; 
	HTREEITEM hTreeItem; 
 
	char *lpMsgBuf; 
 
	CListCtrl *pList = (CListCtrl*)pDlg->GetDlgItem(IDC_LSTFILES); 
	CTreeCtrl *pcTree = (CTreeCtrl *)pDlg->GetDlgItem(IDC_TREDISKS); 
 
	hTreeItem = pcTree->GetSelectedItem(); 
	if(!hTreeItem) 
		goto exitThread;; 
 
	pDrive = (DRIVEPACKET *)pcTree->GetItemData(hTreeItem); 
 
	if(!pDrive) 
		goto exitThread;; 
	 
	// delete the previous files if entered 
	pList->DeleteAllItems(); 
 
	if(pDlg->m_hDrive == INVALID_HANDLE_VALUE) 
	{ 
		pDlg->m_hDrive = CreateFile(PHYSICAL_DRIVE,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,NULL); 
		if(pDlg->m_hDrive == INVALID_HANDLE_VALUE) 
		{ 
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
			pDlg->MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
			LocalFree(lpMsgBuf); 
			CloseHandle(pDlg->m_hDrive); 
			goto exitThread;; 
		} 
	} 
 
	pDlg->m_cNTFS.SetDriveHandle(pDlg->m_hDrive); // set the physical drive handle 
	pDlg->m_cNTFS.SetStartSector(pDrive->dwNTRelativeSector,512); // set the starting sector of the NTFS 
 
	nRet = pDlg->m_cNTFS.Initialize(); // initialize, ie. read all MFT in to the memory 
	if(nRet) 
	{ 
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,nRet, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
		pDlg->MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
		LocalFree(lpMsgBuf); 
		CloseHandle(pDlg->m_hDrive); 
		pDlg->m_hDrive = INVALID_HANDLE_VALUE; 
		goto exitThread;; 
	} 
 
	for(i=0;(i<0xFFFFFFFF);i++) // theoretical max file count is 0xFFFFFFFF 
	{								//   but i'm not sure our CListCtrl can support this ... 
		if(pDlg->m_bStopScanFilesThread) 
			break; 
 
		nRet = pDlg->m_cNTFS.GetFileDetail(i+30,stFInfo); // get the file detail one by one  
		if((nRet == ERROR_NO_MORE_FILES)||(nRet == ERROR_INVALID_PARAMETER)) 
			goto exitThread;; 
 
		if(nRet) 
		{ 
			FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,nRet, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); 
			pDlg->MessageBox((LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR); 
			LocalFree(lpMsgBuf); 
			CloseHandle(pDlg->m_hDrive); 
			pDlg->m_hDrive = INVALID_HANDLE_VALUE; 
			goto exitThread;; 
		} 
 
		pList->InsertItem(i,stFInfo.szFilename); 
 
		strcpy(szBuffer,""); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_READONLY) 
			strcat(szBuffer,"R-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_HIDDEN) 
			strcat(szBuffer,"H-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_SYSTEM) 
			strcat(szBuffer,"S-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_DIRECTORY) 
			strcat(szBuffer,"D-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_ARCHIVE) 
			strcat(szBuffer,"A-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_ENCRYPTED) 
			strcat(szBuffer,"E-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_NORMAL) 
			strcat(szBuffer,"N-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_TEMPORARY) 
			strcat(szBuffer,"T-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_SPARSE_FILE) 
			strcat(szBuffer,"Sp-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_REPARSE_POINT) 
			strcat(szBuffer,"ReSp-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_COMPRESSED) 
			strcat(szBuffer,"C-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_OFFLINE) 
			strcat(szBuffer,"O-"); 
 
		if(stFInfo.dwAttributes&FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) 
			strcat(szBuffer,"I-"); 
 
		if(stFInfo.dwAttributes&0x4000) 
			strcat(szBuffer,"En-");  // if it is encrypted 
 
		if(stFInfo.dwAttributes&0x10000000) 
			strcat(szBuffer,"Dir-"); // if it is directory 
 
		if(stFInfo.dwAttributes&0x10000000) 
			strcat(szBuffer,"In-"); // if it is indexed 
 
		szBuffer[strlen(szBuffer)-1] = 0; 
		pList->SetItemText(i,2,szBuffer); 
 
		sprintf(szBuffer,"%d",i); 
		pList->SetItemText(i,1,szBuffer); 
 
		strcpy(szBuffer,""); 
		if(stFInfo.bDeleted) 
		{ 
			dwDeleted++; 
			strcpy(szBuffer,"Yes"); 
		} 
 
		pList->SetItemText(i,3,szBuffer); 
 
		sprintf(szBuffer,"%u",stFInfo.n64Size); 
		pList->SetItemText(i,4,szBuffer); 
 
		pDlg->SetDlgItemInt(IDC_EDTTOTFILES,i); 
		pDlg->SetDlgItemInt(IDC_EDTDELFILES,dwDeleted); 
	} 
exitThread: 
	pDlg->SetDlgItemText(IDC_BTNSCAN,"Scan Files"); 
	pDlg->GetDlgItem(IDC_BTNSCAN)->EnableWindow(true); 
	return 0; 
}