/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1996 - 1998 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/
// FILLFILE.C
#include "cfiler.h"
extern HANDLE ghDrvThread;
extern HWND ghwndDrv;
/********************************************************************************\
* FillFile()
*
* in parameters
* lpCInfo - instance data for drive child
* hwnd - HWND specified by caller
*
* purpose:
* Fills the file listbox with strings constructed from the contents of the
* directory that is highlighted in the directory listbox.
* This is accomplished by building a file string table with hidden and displayed
* string pairs. The hidden strings are the full pathnames as they exist on the
* disk. The displayed strings are specially formatted strings containing file
* and directory names to be displayed in the owner-draw listbox. The listbox
* knows how to appropriately draw these file and directory names because the
* strings have some special characters at the beginning. Once the string table
* has been constructed, a function called TableSend is called, which generates
* LB_ADDSTRING messages to the listbox, one for each displayed string in the
* table.
*
* returns:
* TRUE if successful
* FALSE if unsuccessful
\********************************************************************************/
BOOL FillFile(LPCINFO lpCInfo, HWND hwnd) {
BOOLbHasSignature = FALSE;
BOOLfNextFile = TRUE;
BOOLfSearchFlag = TRUE;
DWORDdwLastError = ERROR_SUCCESS;
HANDLEhFindFile;
HANDLEhFileRead;
INTi;
TCHARszDecryptedName[PATH_SIZE];
TCHARszFileName[PATH_SIZE];
TCHARszFind[PATH_SIZE];
TCHAR szFiles[PATH_SIZE];
TCHARszBuf[PATH_SIZE];
WIN32_FIND_DATAFindFileData;
LONGlIndex;
TABLEsigtable;
if (!lpCInfo) {
ErrorMsg(TEXT("FillFile: lpCInfo is NULL."));
return FALSE;
}
if( WaitForSingleObject(lpCInfo->hFileMutex, MUTEX_TIMEOUT)
== WAIT_TIMEOUT) {
ErrorMsg(TEXT("FillFile: File LB Mutex Timeout."));
return 0;
}
TableFree(lpCInfo->FileTable);
lpCInfo->FileTable = TableNew();
if (!lpCInfo->FileTable) {
ErrorMsg(TEXT("MM_FILLFILE: TableNew failed."));
return 0;
}
SendMessage(lpCInfo->hFileLB, LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL);
// Put the full pathname of the directory into szFind
// by accessing the directory string table.
lIndex = SendMessage( lpCInfo->hDirLB, LB_GETCARETINDEX,
(WPARAM)NULL, (LPARAM)NULL );
if (!TableGetHidden(lpCInfo->DirTable, lIndex, szFind)) {
ErrorMsg(TEXT("FillFile: TableGetHidden failed."));
return 0;
}
// if szFind has a '\' append a * otherwise append '\*'
if (szFind[lstrlen(szFind) - 1] == TEXT('\\'))
szFind[lstrlen(szFind) - 1] = TEXT('\0');
lstrcpy(szFiles, szFind);
lstrcat(szFind, TEXT("\\*"));
if ((hFindFile = FindFirstFile(szFind, &FindFileData))
== INVALID_HANDLE_VALUE) {
ReleaseMutex(lpCInfo->hFileMutex);
ErrorMsg(TEXT("FillFile: FindFirstFile failed."));
ReleaseMutex(lpCInfo->hFileMutex);
return 0;
}
sigtable = TableNew();
if (!sigtable) {
ErrorMsg(TEXT("FillFile: TableNew failed."));
return 0;
}
BuildSigTable(sigtable);
// Loop through, calling FindNextFiles until no more files are left.
for (i = 0; fNextFile || dwLastError != ERROR_NO_MORE_FILES; i++) {
lstrcpy(szFileName, szFiles);
lstrcat(szFileName, TEXT("\\"));
lstrcat(szFileName, FindFileData.cFileName);
bHasSignature = FALSE;
// If szFileName is not a directory, check if it has a signature.
if (!CFilerIsDirectory(szFileName))
HasSignature(szFileName, sigtable, &bHasSignature);
if (IsEncrypted(szFileName)) {
BOOL fIsValidEncryptedFile = TRUE;
if (!CFilerIsDirectory(szFileName)) {
if (!GetDecryptedFileName(hwnd, szFileName, szDecryptedName, &hFileRead)) {
fIsValidEncryptedFile = FALSE;
lstrcpy(szBuf, TEXT("\0"));
}
CloseHandle(hFileRead);
}
else
GetDecryptedDirName(hwnd, szFileName, szDecryptedName, 0, &hFileRead);
if (fIsValidEncryptedFile) {
if (!bHasSignature)
// '|' indicates to the the owner-draw listbox
// an encrypted file or directory
// This is not unwholesome since '|' is not a legal
// character for a file or directory identifier.
lstrcpy(szBuf, TEXT("|"));
else if (bHasSignature)
// '>' indicates an encrypted file that has been signed.
// This is not unwholesome since '>' is not a legal character
// for a file or directory identifier.
lstrcpy(szBuf, TEXT(">"));
}
lstrcat(szBuf, szDecryptedName);
// add to string table.
if (IsLegalToAdd(FindFileData.cFileName)) {
if (!TableAdd(lpCInfo->FileTable, FindFileData.cFileName, szBuf)) {
ErrorMsg(TEXT("FillFile: TableAdd failed."));
return FALSE;
}
}
}
else {
// Not encrypted
if (CFilerIsDirectory(szFileName)) {
// For directories, enclose the directory name with brackets
// before inserting into string table.
lstrcpy(szBuf, TEXT("["));
lstrcat(szBuf, FindFileData.cFileName);
lstrcat(szBuf, TEXT("]"));
// Add directory name to string table.
if (IsLegalToAdd(FindFileData.cFileName)) {
if (!TableAdd(lpCInfo->FileTable, szBuf, szBuf)) {
ErrorMsg(TEXT("FillFile: TableAdd failed."));
return FALSE;
}
}
}
else if (!CFilerIsDirectory(szFileName)) {
// Not a directory and not encrypted
if (!bHasSignature)
lstrcpy(szBuf, FindFileData.cFileName);
else if (bHasSignature) {
// ';' indicates a signed file. This is
// not unwholesome since ';' is not a legal
// character for a filename.
lstrcpy(szBuf, TEXT(";"));
lstrcat(szBuf, FindFileData.cFileName);
}
// Add filename to string table.
if (IsLegalToAdd(FindFileData.cFileName)) {
if (!TableAdd(lpCInfo->FileTable, FindFileData.cFileName, szBuf)) {
ErrorMsg(TEXT("FillFile: TableAdd failed."));
return FALSE;
}
}
}
}
fNextFile = FindNextFile(hFindFile, &FindFileData);
dwLastError = GetLastError();
}
// sort the file string table on its displayed members
// using the same string compare routine
// that the owner-draw listbox uses.
if (!TableSort(lpCInfo->FileTable, CFilerlstrcmp)) {
ErrorMsg(TEXT("FillFile: selection failed."));
return 0;
}
// send all of the displayed members of the file string table
// to the owner-draw listbox.
// It does not matter in what order they are sent since the
// owner-draw listbox will sort them anyway.
if (GetSize(lpCInfo->FileTable) && !TableSend(lpCInfo->FileTable, lpCInfo->hFileLB)) {
ErrorMsg(TEXT("FillFile: TableSend failed."));
return 0;
}
//
// Set selection to first file.
//
if (GetSize(lpCInfo->FileTable)) {
if(SendMessage(lpCInfo->hFileLB, LB_SETSEL, (WPARAM)TRUE, (LPARAM)0) == LB_ERR) {
ErrorMsg(TEXT("FillFile: Listbox selection failure."));
ReleaseMutex( lpCInfo->hFileMutex );
return 0;
}
}
if (!SetWindowText(lpCInfo->hTextWnd, lpCInfo->CaptionBarText)) {
ErrorMsg(TEXT("FillFile: SetWindowText failed."));
return FALSE;
}
TableFree(sigtable);
ReleaseMutex( lpCInfo->hFileMutex );
FindClose(hFindFile);
return TRUE;
}
/************************************************************************\
* BuildSigTable()
*
* input:
* sigtable - pointer to an empty string table
*
* purpose:
* Builds a string table with displayed fields containing
* the filenames of all the files in the \sig directory on the
* same drive as the system directory.
*
* returns
* TRUE if successful
* FALSE if unsuccessful
\************************************************************************/
BOOL BuildSigTable(TABLE sigtable)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFindFile;
TCHAR szFiles[PATH_SIZE];
TCHAR szFileName[PATH_SIZE];
TCHAR szSystemDirectory[PATH_SIZE];
TCHAR szSigDir[PATH_SIZE];
// [system directory drive]:\sig -> szSigDir
GetSystemDirectory(szSystemDirectory, PATH_SIZE * sizeof(*szSystemDirectory));
szSigDir[0] = szSystemDirectory[0];
szSigDir[1] = TEXT('\0');
lstrcat(szSigDir, TEXT(":\\sig"));
lstrcpy(szFiles, szSigDir);
lstrcat(szFiles, TEXT("\\*"));
hFindFile = FindFirstFile(szFiles, &FindFileData);
if (hFindFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
// insert all the signature filenames into the table sigtable.
do {
lstrcpy(szFileName, szSigDir);
lstrcat(szFileName, TEXT("\\"));
lstrcat(szFileName, FindFileData.cFileName);
TableInsert(sigtable, TEXT("NULL"), szFileName, 0);
} while (FindNextFile(hFindFile, &FindFileData)
|| GetLastError() != ERROR_NO_MORE_FILES);
FindClose(hFindFile);
}
/*************************************************************************************\
* GetLBText()
*
* Gets the text of the currently selected (careted) item in the given
* listbox.
*
* Returns: Index of selected item if successful, -1 on failure
\*************************************************************************************/
LONG GetLBText(HWND hActiveLB, PTCHAR szItemBuff)
{
LONG lIndex;
//
// Retrieve selected (careted) item.
//
lIndex = SendMessage( hActiveLB, LB_GETCARETINDEX,
(WPARAM)NULL, (LPARAM)NULL );
if( SendMessage( hActiveLB, LB_GETTEXT, (WPARAM)lIndex,
(LPARAM)szItemBuff) == LB_ERR ){
ErrorMsg(TEXT("LBN_DBLCLK: Text retrieval failure."));
return(-1);
}
return( lIndex );
}
/*************************************************************************************\
* UpdateFileLB()
*
* Updates the file listbox of the drive child given by sending an MM_FILLFILE
* message to it.
*
* input: hwnd - Handle of drive child to update file listbox of.
\*************************************************************************************/
VOID UpdateFileLB(HWND hwnd)
{
LPCINFO lpCInfo;
lpCInfo = (LPCINFO)GetWindowLong(hwnd, GWL_USERDATA);
SendMessage(hwnd, WM_COMMAND, (WPARAM)MM_FILLFILE, (LPARAM)0);
}
/*************************************************************************************\
* RunListBoxItem()
*
* input: lpCInfo - pointer to Drv child's LPCINFO structure
* cmd - integer specifying what action to perform on
* the file corresponding to the selected
* file listbox text.
*
* purpose:
* 1. Obtains the full pathname of the selected directory or file
* in the file listbox.
* 2. Depending on whether a directory or file has been selected and
* depending on cmd, the appropriate action is taken:
* - CFILEREncryptFile()
* - EncryptDir()
* - CFILERDecryptFile()
* - DecryptDir()
* - SignFile()
* - VerifyFile()
*
* Returns TRUE if successful, FALSE if unsuccessful.
* If a user tries to sign a directory, RunListBoxItem returns FALSE.
\*************************************************************************************/
BOOL RunListBoxItem(LPCINFO lpCInfo, int cmd)
{
LONGlIndex;
TCHARszBuf[PATH_SIZE];
TCHARszFileName[PATH_SIZE];
TCHARszBuf2[PATH_SIZE];
if (!lpCInfo) {
ErrorMsg(TEXT("RunListBoxItem: lpCInfo is NULL."));
return FALSE;
}
// get index of selected item in Directory listbox.
lIndex = SendMessage( lpCInfo->hDirLB, LB_GETCARETINDEX,
(WPARAM)NULL, (LPARAM)NULL );
// obtain full pathname of directory corresponding to selected text in
// directory listbox by accessing the string table for the directory listbox.
if (!TableGetHidden(lpCInfo->DirTable, lIndex, szFileName)) {
ErrorMsg(TEXT("RunListBoxItem: TableGetHidden failed."));
return FALSE;
}
// append a '\\' to the end of the full pathname if one isn't already there.
if (szFileName[lstrlen(szFileName) - 1] != TEXT('\\')) {
if (!lstrcat(szFileName, TEXT("\\"))) {
ErrorMsg(TEXT("RunListBoxItem: lstrcat failed."));
return FALSE;
}
}
//
// Retrieve selected (careted) item.
//
// get index of selected item in the file listbox.
lIndex = GetLBText(lpCInfo->hFileLB, szBuf);
if (lIndex == LB_ERR) {
ErrorMsg(TEXT("RunListBoxItem: GetLBText failed."));
return FALSE;
}
// get the full pathname of the file corresponding to the selected text
// in the file listbox by accessing the string table for the
// file listbox.
if (!TableGetHidden(lpCInfo->FileTable, lIndex, szBuf)) {
ErrorMsg(TEXT("RunListBoxItem: TableGetHidden failed."));
return FALSE;
}
if (WaitForSingleObject(ghDrvThread, INFINITE) == WAIT_FAILED) {
ErrorMsg(TEXT("RunListBoxItem: WaitForSingleObject failed."));
return FALSE;
}
if (lpCInfo->hDirThread
&& WaitForSingleObject(lpCInfo->hDirThread, INFINITE) == WAIT_FAILED) {
ErrorMsg(TEXT("RunListBoxItem: WaitForSingleObject failed."));
return FALSE;
}
lstrcpy(szBuf2, szBuf);
SimplifyFileName(szBuf2, szBuf);
lstrcat(szFileName, szBuf);
// if szFileName is not encrypted and the user wants to encrypt/decrypt
if (!IsEncrypted(szFileName) && cmd == ENCRYPT_DECRYPT) {
// if szFileName is a directory
if (CFilerIsDirectory(szFileName)) {
// encrypt the directory
if (!EncryptDir(ghwndDrv, szFileName, lpCInfo)) {
ErrorMsg(TEXT("RunListBoxItem: EncryptDir failed."));
return FALSE;
}
}
// not a directory
else {
// encrypt the file
if(!CFILEREncryptFile(ghwndDrv, szFileName)) {
ErrorMsg(TEXT("RunListBoxItem: CFILEREncryptFile failed."));
return FALSE;
}
}
UpdateFileLB(ghwndDrv);
}
else if (cmd == ENCRYPT_DECRYPT) {
// if szFileName is a directory
if (CFilerIsDirectory(szFileName)) {
// decrypt the directory.
if (!DecryptDir(ghwndDrv, szFileName, lpCInfo)) {
ErrorMsg(TEXT("RunListBoxItme: DecryptDir failed."));
return FALSE;
}
}
else {
// not a directory
if (!CFILERDecryptFile(ghwndDrv, szFileName)) {
ErrorMsg(TEXT("RunListBoxItem: CFILERDecryptFile failed."));
return FALSE;
}
}
UpdateFileLB(ghwndDrv);
}
else if (cmd == SIGN) {
// sign file if szFileName is not a directory
if (!CFilerIsDirectory(szFileName) && !SignFile(ghwndDrv, szFileName)) {
ErrorMsg(TEXT("RunListBoxItem: SignFile failed."));
return FALSE;
}
UpdateFileLB(ghwndDrv);
}
else if (cmd == VERIFY) {
// verify file is szFileName is not a directory.
if (!CFilerIsDirectory(szFileName) && !VerifyFile(ghwndDrv, szFileName)) {
ErrorMsg(TEXT("RunListBoxItem: VerifyFile failed."));
return FALSE;
}
UpdateFileLB(ghwndDrv);
}
return TRUE;
}
/*************************************************************************************\
* CFilerIsDirectory()
*
* input - szDirName: In Parameter: Buffer containing full pathname of directory
*
* Purpose: returns TRUE if szDiretory is a directory or a hidden directory,
* FALSE otherwise or if error.
\*************************************************************************************/
BOOL CFilerIsDirectory(LPTSTR szDirName) {
DWORD dwFileAttributes;
if (!szDirName) {
ErrorMsg(TEXT("CFilerIsDirectory: szDirName is NULL."));
return FALSE;
}
dwFileAttributes = GetFileAttributes(szDirName);
if (dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
return TRUE;
if (dwFileAttributes == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN))
return TRUE;
return FALSE;
}
/*************************************************************************************\
* SeparatePathName()
*
* First parameter (in parameter): szFileName - full path name to be separated
*
* Second parameter (out parameter): szDir - buffer to hold full pathname of directory
*
* Third parameter (out parameter): szFile - buffer to hold filename (not full pathname)
*
* Example: C:\directory\[foo] -> C:\directory + [foo]
\*************************************************************************************/
BOOL SeparatePathName(LPTSTR szFileName, LPTSTR szDir, LPTSTR szFile) {
INTi, j, nLen, nFileOffset;
if (!szFileName) {
ErrorMsg(TEXT("SeparatePathName: szFileName is NULL."));
return FALSE;
}
if (!szDir) {
ErrorMsg(TEXT("SeparatePathName: szDir is NULL."));
return FALSE;
}
if (!szFile) {
ErrorMsg(TEXT("SeparatePathName: szFile is NULL."));
return FALSE;
}
lstrcpy(szDir, TEXT("\0"));
lstrcpy(szFile, TEXT("\0"));
nLen = lstrlen(szFileName);
if (szFileName[nLen - 1] == TEXT('\\'))
for (i = nLen - 1; szFileName[i] != TEXT('\\') && i; i--);
else
for (i = nLen; szFileName[i] != TEXT('\\') && i; i--);
nFileOffset = i + 1;
for (i = 0; i < nFileOffset - 1; i++)
szDir[i] = szFileName[i];
szDir[i] = TEXT('\0');
for (j = 0, i++; i < lstrlen(szFileName); i++, j++)
szFile[j] = szFileName[i];
szFile[j] = TEXT('\0');
return TRUE;
}
/*************************************************************************************\
* SeparatePathName2()
*
* First parameter (in parameter): szFileName - full path name to be separated
*
* Second parameter (out parameter): szDir - buffer to hold full pathname of directory
*
* Third parameter (out parameter): szFile - buffer to hold filename (not full pathname)
*
* brackets are stripped from the filename before the filename is inserted into szFile.
*
* C:\directory\[foo] -> C:\directory + foo
\*************************************************************************************/
BOOL SeparatePathName2(LPTSTR szFileName, LPTSTR szDir, LPTSTR szFile) {
INTi, j, nLen, nFileOffset;
if (!szFileName) {
ErrorMsg(TEXT("SeparatePathName2: szFileName is NULL."));
return FALSE;
}
if (!szDir) {
ErrorMsg(TEXT("SeparatePathName2: szDir is NULL."));
return FALSE;
}
if (!szFile) {
ErrorMsg(TEXT("SeparatePathName2: szFile is NULL."));
return FALSE;
}
lstrcpy(szDir, TEXT("\0"));
lstrcpy(szFile, TEXT("\0"));
nLen = lstrlen(szFileName);
if (szFileName[nLen - 1] == TEXT('\\'))
for (i = nLen - 1; szFileName[i] != TEXT('\\') && i; i--);
else
for (i = nLen; szFileName[i] != TEXT('\\') && i; i--);
nFileOffset = i + 1;
for (i = 0; i < nFileOffset - 1; i++)
szDir[i] = szFileName[i];
szDir[i] = TEXT('\0');
for (j = 0, i++; i < lstrlen(szFileName); ) {
if (szFileName[i] == TEXT('[') || szFileName[i] == TEXT(']'))
i++;
else {
szFile[j] = szFileName[i];
i++;
j++;
}
}
szFile[j] = TEXT('\0');
return TRUE;
}
/*************************************************************************************\
* IsEncrypted()
*
* input:
*
* szFileName - In parameter: buffer containing filename
*
* If szFileName has a .CRP extension, IsEncrypted() returns TRUE, FALSE otherwise
* or if failure.
\*************************************************************************************/
BOOL IsEncrypted(LPTSTR szFileName) {
INT nLen;
if (!szFileName) {
ErrorMsg(TEXT("IsEncrypted: szFileName is NULL."));
return FALSE;
}
nLen = lstrlen(szFileName);
if (szFileName[nLen - 4] == TEXT('.') &&
szFileName[nLen - 3] == TEXT('C') &&
szFileName[nLen - 2] == TEXT('R') &&
szFileName[nLen - 1] == TEXT('P'))
return TRUE;
return FALSE;
}
/*************************************************************************************\
* IsLegalToAdd()
*
* input
* in parameters
* szFileName - buffer containing filename (not full pathname) of file in question
*
* purpose
* determines whether szFileName is a file or directory that should be added to
* the file listbox string table.
*
* returns
* TRUE if szFileName is legal
* FALSE otherwise
\*************************************************************************************/
BOOL IsLegalToAdd(LPTSTR szFileName)
{
if (lstrcmp(szFileName, TEXT(".."))
&& lstrcmp(szFileName, TEXT("."))
&& lstrcmp(szFileName, TEXT("dirinfo")))
return TRUE;
return FALSE;
}