POPFILE.C


/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1992 - 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.
\******************************************************************************/

//+---------------------------------------------------------------------------
//
// File: popfile.c
//
// Contents:
//
// Classes:
//
// Functions:
//
//----------------------------------------------------------------------------

#include "pop3srvp.h"
#pragma hdrstop

#define POP3_LOCKFILE TEXT("poplock")
#define POP3_LOCKFILE_NAME TEXT("\\") POP3_LOCKFILE
#define POP3_SEARCH TEXT("\\*.*")


WCHAR BaseDirectory[MAX_PATH];

//+---------------------------------------------------------------------------
//
// Function: LockMailDirectory
//
// Synopsis: Attempts to lock the mail directory
//
// Arguments: [hUserToken] -- Token of user
// [pszPath] -- path to the mail directory
//
// Returns: Handle of lock file on success, or NULL
//
// History: 1-06-95 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
HANDLE
LockMailDirectory(
HANDLE hUserToken,
PCHAR pszPath)
{

WCHAR PathToOpen[MAX_PATH];
WCHAR WidePath[64];
HANDLE hLockFile;

//
// Build lock file name
//
MultiByteToWideChar(
CP_ACP, MB_PRECOMPOSED,
pszPath, -1,
WidePath, sizeof(WidePath) / sizeof(WCHAR) );

wcscpy(PathToOpen, BaseDirectory);
wcscat(PathToOpen, WidePath);
wcscat(PathToOpen, POP3_LOCKFILE_NAME);

//
// Impersonate the client
//
#ifdef SECURE_BUILD

ImpersonateLoggedOnUser(hUserToken);

#endif

//
// Attempt to create the file. This will fail if it already exists,
// which would indicate that another thread/client is accessing this
// mailbox.
//
DebugLog((DEB_TRACE, "Opening lock file as %ws\n", PathToOpen));

hLockFile = CreateFile( PathToOpen,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_DELETE_ON_CLOSE,
NULL);

//
// Done being the client. Back to server security
//
RevertToSelf();

//
// Return a handle, or NULL if failed
//
return(hLockFile != INVALID_HANDLE_VALUE ? hLockFile : NULL);

}

//+---------------------------------------------------------------------------
//
// Function: OpenMailMessage
//
// Synopsis: Opens the specified mail message as the user
//
// Arguments: [MessageId] --
// [pDir] --
// [hUserToken] --
//
// History: 1-08-95 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
HANDLE
OpenMailMessage(
DWORD MessageId,
PPopMailDirectory pDir,
HANDLE hUserToken)
{
HANDLE hMailFile;
WCHAR Path[MAX_PATH];

//
// Impersonate the client
//
#ifdef SECURE_BUILD

ImpersonateLoggedOnUser(hUserToken);

#endif

//
// Attempt to create the file. This will fail if it already exists,
// which would indicate that another thread/client is accessing this
// mailbox.
//
wcscpy(Path, pDir->pBaseDir);
wcscat(Path, TEXT("\\"));
wcscat(Path, pDir->Messages[MessageId].pszFileName);

hMailFile = CreateFile( Path,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_HIDDEN,
NULL);

//
// Done being the client. Back to server security
//
RevertToSelf();

//
// Return a handle, or NULL if failed
//
return(hMailFile != INVALID_HANDLE_VALUE ? hMailFile : NULL);
}


//+---------------------------------------------------------------------------
//
// Function: UnlockMailDirectory
//
// Synopsis: Unlocks the mail directory
//
// Arguments: [hLockFile] -- Handle of lock file to close
//
// Returns: TRUE if success, FALSE if failure
//
// History: 1-06-95 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL
UnlockMailDirectory(
HANDLE hLockFile)
{
//
// Since the lock file was opened with DELETE_ON_CLOSE semantics, it will
// softly and silently vanish away when we close this, the one handle to
// it.
//

return(CloseHandle(hLockFile));
}



//+---------------------------------------------------------------------------
//
// Function: ReadMailDirectory
//
// Synopsis: Reads in a list of all the files in the directory
//
// Arguments: [hUserToken] --
// [pszPath] --
//
// Returns:
//
// History: 1-08-95 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
PPopMailDirectory
ReadMailDirectory(
HANDLE hUserToken,
PCHAR pszPath)
{
WIN32_FIND_DATA FindData;
PPopMailDirectory pDir;
WCHAR MailDir[MAX_PATH];
WCHAR WidePath[64];
HANDLE hSearch;
PPopMessageHeader pExtraHeaders;
PPopMessageHeader pHeader;
DWORD RemainingHeaders;

MultiByteToWideChar(
CP_ACP, MB_PRECOMPOSED,
pszPath, -1,
WidePath, sizeof(WidePath) / sizeof(WCHAR) );
wcscpy(MailDir, BaseDirectory);
wcscat(MailDir, WidePath);

pDir = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(PopMailDirectory));
pDir->pBaseDir = LocalAlloc(LMEM_FIXED, (wcslen(MailDir) + 1) * sizeof(WCHAR));
wcscpy(pDir->pBaseDir, MailDir);

wcscat(MailDir, POP3_SEARCH);

#ifdef SECURE_BUILD

ImpersonateLoggedOnUser(hUserToken);

#endif

hSearch = FindFirstFile(MailDir, &FindData);

if (hSearch == INVALID_HANDLE_VALUE)
{
DebugLog((DEB_TRACE, "FindFirst FAILED!, %d\n", GetLastError()));
RevertToSelf();

return(NULL);
}

pExtraHeaders = LocalAlloc(LMEM_FIXED, sizeof(PopMessageHeader) * 10);
RemainingHeaders = 10;
pHeader = pExtraHeaders;

do
{
if (FindData.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_HIDDEN) )
{
continue; // Skip non-normal files
}
if (wcsicmp(FindData.cFileName,POP3_LOCKFILE) == 0)
{
continue; // Skip our lock file
}
DebugLog((DEB_TRACE, "ReadDir: Message %ws, size %d\n",
FindData.cFileName, FindData.nFileSizeLow));

pHeader->Flags = 0;
pDir->TotalSize += FindData.nFileSizeLow;
pHeader->Size = FindData.nFileSizeLow;

pHeader->pszFileName = LocalAlloc(LMEM_FIXED,
(wcslen(FindData.cFileName) + 1) * sizeof(WCHAR) );

wcscpy(pHeader->pszFileName, FindData.cFileName);
pHeader++;
RemainingHeaders--;



if (RemainingHeaders == 0)
{
PPopMessageHeader pTemp;


pTemp = LocalAlloc(LMEM_FIXED, sizeof(PopMessageHeader) * (pDir->cMessages + 20));

CopyMemory(pTemp, pExtraHeaders, sizeof(PopMessageHeader) * (pDir->cMessages + 10));

LocalFree(pExtraHeaders);

pExtraHeaders = pTemp;

RemainingHeaders = 10;

pDir->cMessages += 10;
}

} while (FindNextFile(hSearch, &FindData));

pDir->cMessages += (10 - RemainingHeaders);
pDir->Messages = pExtraHeaders;

FindClose(hSearch);

pDir->cAvailMessages = pDir->cMessages;
pDir->AvailSize = pDir->TotalSize;

RevertToSelf();

return(pDir);
}

BOOL
CommitMailDirectory(
PPopMailDirectory pDir,
HANDLE hUserToken)
{
DWORD i;
WCHAR Path[MAX_PATH];
PWSTR pszPath;

wcscpy(Path, pDir->pBaseDir);
wcscat(Path, TEXT("\\"));
pszPath = Path + wcslen(Path);


#ifdef SECURE_BUILD

ImpersonateLoggedOnUser(hUserToken);

#endif

for (i = 0; i < pDir->cMessages ; i++)
{
if (pDir->Messages[i].Flags & POP3_MESSAGE_DELETE)
{
wcscpy(pszPath, pDir->Messages[i].pszFileName);
DeleteFile(Path);
}
}

RevertToSelf();

return(TRUE);
}

void
FreeMailDirectory(
PPopMailDirectory pDir)
{
DWORD i;

for (i = 0 ; i < pDir->cMessages ; i++ )
{
LocalFree(pDir->Messages[i].pszFileName);
}

LocalFree(pDir->Messages);
LocalFree(pDir);

}