/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1993 - 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.
\******************************************************************************/
/****************************** Module Header *******************************
* Module Name: file.c
*
* This file contains the high level routines that begin opening
* and saving files.
*
* Functions:
* Open()
* BuildFilterString()
* DoWeSave()
* Save()
* OpenCmdLineFile()
* FileInPath()
* ShowFileStatus()
* DifferentDirs()
* HasPath()
* WriteDWordPad()
* BuildDefSaveName()
* WriteTheFile()
* FormTempFileName()
* FileCat()
*
* Comments:
*
****************************************************************************/
#include "dlgedit.h"
#include "dlgfuncs.h"
#include "dlgextrn.h"
#include "dialogs.h"
#include <wchar.h>
#include <commdlg.h>
/*
* File types.
*/
#define FILE_RES 0 // Resource (.RES) file.
#define FILE_DLG 1 // Dialog (.DLG) file.
#define FILE_INC 2 // Include (.H) file.
STATICFN VOID BuildDefSaveName(INT FileType, LPTSTR pszFullFileName,
LPTSTR pszFileName, LPTSTR pszOtherFullFileName, LPTSTR pszOtherFileName,
LPTSTR pszFullFileNameBuffer, INT cchBuffer);
STATICFN BOOL WriteTheFile(LPTSTR pszFile, INT fmt);
STATICFN VOID FormTempFileName(LPTSTR pszBaseName, LPTSTR pszBuffer);
STATICFN VOID FileCat(LPTSTR pchName, LPTSTR pchCat, BOOL fChop);
/************************************************************************
* Open
*
* Handles opening of resource and include files.
* Saves current dialog in the resource.
* Might put up a message box.
* Cancels moves.
* Changes szFullResFile, pszResFile, szFullIncludeFile, pszIncludeFile
* Puts up dialog boxes.
* Restores dialog box from resource.
* Sets changed flags.
*
* Arguments:
* INT FileType - FILE_RESOURCE or FILE_INCLUDE.
*
* Returns:
* TRUE if successful, FALSE if not.
*
************************************************************************/
BOOL Open(
INT FileType)
{
BOOL fSuccess;
BOOL fGotName;
OPENFILENAME ofn;
TCHAR szNewFileName[CCHMAXPATH];
TCHAR szInitialDir[CCHMAXPATH];
TCHAR szFilter[CCHTEXTMAX];
INT idPrevDlg;
/*
* Cancel any outstanding selection(s).
*/
CancelSelection(TRUE);
/*
* Put current dialog back into the resource buffer.
*/
if (!SynchDialogResource())
return FALSE;
/*
* Begin setting up the globals and the open file dialog structure.
*/
fSuccess = FALSE;
*szNewFileName = CHAR_NULL;
/*
* Build up the filter string.
*/
BuildFilterString(FileType, szFilter);
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = ghwndMain;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szNewFileName;
ofn.nMaxFile = CCHMAXPATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
if (FileType == FILE_INCLUDE) {
/*
* If there is a res file, set the default include file
* name to open to be the basename of the res file with
* a .H extension, if such a file exists. We use szInitialDir
* here as a temporary buffer.
*/
if (pszResFile) {
lstrcpy(szInitialDir, szFullResFile);
FileCat(szInitialDir, ids(IDS_DOTH), TRUE);
if (GetFileAttributes(szInitialDir) != -1) {
lstrcpy(szNewFileName, pszResFile);
FileCat(szNewFileName, ids(IDS_DOTH), TRUE);
}
}
ofn.lpstrTitle = ids(IDS_INCOPENTITLE);
ofn.lpstrDefExt = ids(IDS_INCEXT);
}
else {
ofn.lpstrTitle = ids(IDS_RESOPENTITLE);
ofn.lpstrDefExt = ids(IDS_RESEXT);
}
/*
* If they have already opened one res file, start looking for
* any new files to open in the same directory. Otherwise, just
* default to the current directory.
*/
if (pszResFile) {
lstrcpy(szInitialDir, szFullResFile);
*FileInPath(szInitialDir) = CHAR_NULL;
ofn.lpstrInitialDir = szInitialDir;
}
else {
ofn.lpstrInitialDir = NULL;
}
ofn.Flags = OFN_HIDEREADONLY | OFN_SHOWHELP | OFN_FILEMUSTEXIST;
ofn.lCustData = 0;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
/*
* Fire off the dialog box to open the file.
*/
EnteringDialog((FileType == FILE_INCLUDE) ?
DID_COMMONFILEOPENINCLUDE : DID_COMMONFILEOPENRES,
&idPrevDlg, TRUE);
fGotName = GetOpenFileName(&ofn);
EnteringDialog(idPrevDlg, NULL, FALSE);
if (fGotName) {
if (FileType == FILE_INCLUDE) {
if (OpenIncludeFile(szNewFileName)) {
/*
* Since we just loaded a new include file, we mark the
* resource as changed so that the .RES and .DLG files
* will be written out with the proper name in the
* DLGINCLUDE statement.
*/
gfResChged = TRUE;
fSuccess = TRUE;
}
}
else {
if (OpenResFile(szNewFileName))
fSuccess = TRUE;
}
}
ShowFileStatus(TRUE);
return fSuccess;
}
/************************************************************************
* BuildFilterString
*
* This function creates a filter string to be passed into the
* standard file open and save dialogs. This will be something like:
* "Resource (*.res)\0*.res\0\0"
*
* Arguments:
* INT FileType - Flags for type of file, FILE_INCLUDE, FILE_RESOURCE
* or FILE_DLL.
* LPTSTR pszFilter - Where to return the filter string.
*
************************************************************************/
VOID BuildFilterString(
INT FileType,
LPTSTR pszFilter)
{
INT idsFileSpecName;
INT idsFileSpec;
LPTSTR psz;
if (FileType & FILE_INCLUDE) {
idsFileSpecName = IDS_DEFINCFILESPECNAME;
idsFileSpec = IDS_DEFINCFILESPEC;
}
else if (FileType & FILE_RESOURCE) {
idsFileSpecName = IDS_DEFRESFILESPECNAME;
idsFileSpec = IDS_DEFRESFILESPEC;
}
else { // Must be a DLL.
idsFileSpecName = IDS_DEFDLLFILESPECNAME;
idsFileSpec = IDS_DEFDLLFILESPEC;
}
/*
* Build up the filter string. This will be something like:
* "Resource (*.res)\0*.res\0\0"
*/
psz = (LPTSTR)WriteSz(pszFilter, ids(idsFileSpecName));
psz = (LPTSTR)WriteSz(psz, ids(idsFileSpec));
*psz = CHAR_NULL;
}
/************************************************************************
* OpenCmdLineFile
*
* Handles opening of the resource file specified on the command line.
*
* Arguments:
* LPTSTR - pointer to the file name string
*
************************************************************************/
VOID OpenCmdLineFile(
LPTSTR pszFileName)
{
TCHAR szFullPath[CCHMAXPATH];
LPTSTR pszOnlyFileName;
if (SearchPath(L".", pszFileName, ids(IDS_DOTRES), CCHMAXPATH,
szFullPath, &pszOnlyFileName) == -1) {
Message(MSG_CANTOPENRES, pszFileName);
}
else {
OpenResFile(szFullPath);
}
}
/************************************************************************
* DoWeSave
*
* This function checks to see if the include file or the resource file
* needs to be saved. It first checks the changed flags and if TRUE,
* asks the user if they want to save the file. If they say yes, it
* calls Save to do the actual work.
*
* Arguments:
* INT rgbFlags = FILE_RESOURCE or FILE_INCLUDE (but not both).
*
* Returns:
* IDYES - The user wanted to save the file AND the save
* was successful, or the file has not been changed.
* IDNO - The file had been changed but the user did not
* want it saved.
* IDCANCEL - The file had been changed, and either the user wanted
* it saved and the save failed, or they specified that
* they wanted the operation cancelled.
*
************************************************************************/
INT DoWeSave(
INT rgbFlags)
{
LPTSTR pszFile;
INT MsgCode;
BOOL fChanged;
INT nRet = IDYES;
/*
* First set variables for current case.
*/
if (rgbFlags & FILE_RESOURCE) {
fChanged = gfResChged;
MsgCode = MSG_CLOSING;
pszFile = pszResFile ? pszResFile : ids(IDS_UNTITLED);
}
else {
fChanged = gfIncChged;
MsgCode = MSG_INCLCLOSING;
pszFile = pszIncludeFile ? pszIncludeFile : ids(IDS_UNTITLED);
}
if (fChanged) {
nRet = Message(MsgCode, pszFile);
if (nRet == IDYES) {
if (!Save(FILE_NOSHOW | rgbFlags))
nRet = IDCANCEL;
}
}
return nRet;
}
/************************************************************************
* Save
*
* Handles all saving of files based on menu choice. Does a
* CancelSelection and a SynchDialogResource.
*
* Arguments:
* INT rgbFlags - Can include FILE_SHOW, FILE_INCLUDE, FILE_SAVEAS.
*
* Returns:
* TRUE if the file was saved, FALSE if not.
*
************************************************************************/
BOOL Save(
INT rgbFlags)
{
OPENFILENAME ofn;
BOOL fGotName;
LPTSTR pszFileName;
LPTSTR pszFileNameDlg;
LPTSTR pszFullFileName;
BOOL fSuccess = FALSE;
TCHAR szInitialDir[CCHMAXPATH];
TCHAR szSaveFileName[CCHMAXPATH];
TCHAR szSaveFileNameDlg[CCHMAXPATH];
TCHAR szFilter[CCHTEXTMAX];
INT idPrevDlg;
/*
* Put current dialog back into the resource buffer.
*/
if (!SynchDialogResource())
return FALSE;
/*
* If the file being saved has not been named, force a "Save As".
*/
if ((rgbFlags & FILE_INCLUDE) ? !pszIncludeFile : !pszResFile)
rgbFlags |= FILE_SAVEAS;
if (rgbFlags & FILE_SAVEAS) {
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = ghwndMain;
ofn.hInstance = NULL;
/*
* Build up the filter string.
*/
BuildFilterString(rgbFlags, szFilter);
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szSaveFileName;
ofn.nMaxFile = CCHMAXPATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
if (rgbFlags & FILE_INCLUDE) {
ofn.lpstrTitle = ids(IDS_INCSAVETITLE);
ofn.lpstrDefExt = ids(IDS_INCEXT);
BuildDefSaveName(FILE_INCLUDE,
szFullIncludeFile, pszIncludeFile,
szFullResFile, pszResFile,
szInitialDir, CCHMAXPATH);
}
else {
ofn.lpstrTitle = ids(IDS_RESSAVETITLE);
ofn.lpstrDefExt = ids(IDS_RESEXT);
BuildDefSaveName(FILE_RESOURCE,
szFullResFile, pszResFile,
szFullIncludeFile, pszIncludeFile,
szInitialDir, CCHMAXPATH);
}
/*
* At this point, szInitialDir contains the full path to
* the suggested save file name. Find the end of the path,
* copy just the filename to the file name buffer and cut
* the filename portion off the initial directory buffer.
*/
pszFileName = FileInPath(szInitialDir);
lstrcpy(szSaveFileName, pszFileName);
*pszFileName = CHAR_NULL;
ofn.lpstrInitialDir = szInitialDir;
ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_SHOWHELP;
ofn.lCustData = 0;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
/*
* Fire off the dialog box to get the file name to use.
*/
EnteringDialog((rgbFlags & FILE_INCLUDE) ?
DID_COMMONFILESAVEINCLUDE : DID_COMMONFILESAVERES,
&idPrevDlg, TRUE);
fGotName = GetSaveFileName(&ofn);
EnteringDialog(idPrevDlg, NULL, FALSE);
if (fGotName) {
pszFullFileName = szSaveFileName;
pszFileName = FileInPath(szSaveFileName);
fSuccess = TRUE;
}
}
else {
if (rgbFlags & FILE_INCLUDE) {
pszFileName = pszIncludeFile;
pszFullFileName = szFullIncludeFile;
}
else {
pszFileName = pszResFile;
pszFullFileName = szFullResFile;
}
fSuccess = TRUE;
}
if (fSuccess) {
if (rgbFlags & FILE_INCLUDE) {
/*
* Save include file.
*/
if (!WriteTheFile(pszFullFileName, FILE_INC)) {
Message(MSG_CANTCREATE, pszFileName);
fSuccess = FALSE;
}
}
else {
/*
* Form the same name as the .res file but with
* a .dlg extension.
*/
lstrcpy(szSaveFileNameDlg, pszFullFileName);
pszFileNameDlg = FileInPath(szSaveFileNameDlg);
FileCat(pszFileNameDlg, ids(IDS_DOTDLG), TRUE);
/*
* Save .RES file, then the .DLG file. It is done
* in this order so that makes wil notice that the
* .dlg file has a newer time stamp than the .res
* and will cause the .res to be rebuilt. This
* could be necessary to pick up other changes
* in the resources in a project.
*/
if (!WriteTheFile(pszFullFileName, FILE_RES)) {
Message(MSG_CANTCREATE, pszFileName);
fSuccess = FALSE;
}
else if (!WriteTheFile(szSaveFileNameDlg, FILE_DLG)) {
Message(MSG_CANTCREATE, pszFileNameDlg);
fSuccess = FALSE;
}
else {
/*
* Successfully saved both files. Update our
* globals.
*/
lstrcpy(szFullResFile, pszFullFileName);
pszResFile = FileInPath(szFullResFile);
gfResChged = FALSE;
}
}
}
ShowFileStatus(TRUE);
return fSuccess;
}
/************************************************************************
* BuildDefSaveName
*
* This function takes the filenames of the current resource and include
* files and builds the default filename that will be shown in the
* "Save As" dialog. If the current file is still untitled, it will
* attempt to pick a default name based on the other files name.
*
* To use, pass in the file type (FILE_RESOURCE or FILE_INCLUDE) and
* give the current file name and full file name of both the current
* file you are building, and the other type of file. The following
* rules will be followed, in order:
*
* 1. If the file name is valid (not NULL) and it is either the
* include file we are naming or it is the res file but there
* is no include file, it will copy the full file name to the
* output buffer.
*
* 2. If the other file name is valid, it will take this name, add the
* appropriate extension and copy it to the output buffer.
*
* 3. If neither of the file names are valid (they are BOTH untitled),
* it will assume the current directory and make a default file
* name with the appropriate extension.
*
* Rule 1 is a little complicated, but it's purpose is to make it so
* that if a default res file name is being requested, and they changed
* the directory and/or name for the include file that was just saved,
* the default directory and name for the res file will be the same
* directory and base name as the new include file directory and name.
*
* Arguments:
* INT FileType - Either FILE_RESOURE or FILE_INCLUDE.
* LPTSTR pszFullFileName - The full file name. This will only
* be used if pszFileName is not NULL.
* LPTSTR pszFileName - File name to use, or NULL if it is
* currently untitled.
* LPTSTR pszOtherFullFileName - Full file name of the other file. Only
* considered valid if pszOtherFileName is
* not NULL.
* LPTSTR pszOtherFileName - File name of the other file, or NULL if
* it is untitled.
* LPTSTR pszFullFileNameBuffer - Where to put the full file name.
* INT cchBuffer - Size of the buffer in characters.
*
************************************************************************/
STATICFN VOID BuildDefSaveName(
INT FileType,
LPTSTR pszFullFileName,
LPTSTR pszFileName,
LPTSTR pszOtherFullFileName,
LPTSTR pszOtherFileName,
LPTSTR pszFullFileNameBuffer,
INT cchBuffer)
{
TCHAR szBuffer[CCHMAXPATH];
if (pszFileName && (FileType == FILE_INCLUDE || !pszOtherFileName)) {
/*
* Simple case. The file already has a title.
*/
lstrcpy(pszFullFileNameBuffer, pszFullFileName);
}
else if (pszOtherFileName) {
/*
* Copy the other files name and add the proper extension.
*/
lstrcpy(pszFullFileNameBuffer, pszOtherFullFileName);
FileCat(pszFullFileNameBuffer,
(FileType == FILE_INCLUDE) ? ids(IDS_DOTH) :
ids(IDS_DOTRES), TRUE);
}
else {
/*
* Pick a default name in the current directory and
* add the proper extension.
*/
lstrcpy(szBuffer, ids(IDS_DEFSAVENAME));
FileCat(szBuffer,
(FileType == FILE_INCLUDE) ? ids(IDS_DOTH) :
ids(IDS_DOTRES), TRUE);
GetFullPathName(szBuffer, cchBuffer, pszFullFileNameBuffer, NULL);
}
}
/************************************************************************
* WriteTheFile
*
* This function accepts a pointer to a resource buffer and a format
* type. It writes the buffer out in the appropriate format. It
* gets the file name from pszFile, adding the appropriate extension
* for the type of file. The file is first written to a temporary file
* then the old file is removed and finally the new file is renamed.
*
* Arguments:
* LPTSTR pszFile - The name to save to.
* INT fmt - format to write the buffer out in,
* FILE_RES, FILE_INC or FILE_DLG.
*
* Returns:
* TRUE => File successfully written.
* FALSE => Failure in writing file.
*
************************************************************************/
STATICFN BOOL WriteTheFile(
LPTSTR pszFile,
INT fmt)
{
TCHAR szTempFile[CCHMAXPATH]; /* Used for temporary filename */
TCHAR szSrcFile[CCHMAXPATH]; /* Source file with proper extension */
HANDLE hfWrite;
HCURSOR hcurSave;
BOOL fSuccess = FALSE;
WORD idsExt;
hcurSave = SetCursor(hcurWait);
switch (fmt) {
case FILE_RES:
idsExt = IDS_DOTRES;
break;
case FILE_DLG:
idsExt = IDS_DOTDLG;
break;
case FILE_INC:
idsExt = IDS_DOTH;
break;
}
/*
* Append appropriate file name extension.
*/
lstrcpy(szSrcFile, pszFile);
FileCat(szSrcFile, ids(idsExt), fmt == FILE_DLG ? TRUE : FALSE);
/*
* Generate appropriate temporary file name in the same directory.
* It is done in the same directory so that a simple rename can
* be done later.
*/
FormTempFileName(szSrcFile, szTempFile);
if ((hfWrite = CreateFile(szTempFile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL)) == (HANDLE)-1)
goto Exit;
switch (fmt) {
case FILE_RES:
if (!WriteRes(hfWrite, szSrcFile))
goto CloseAndExit;
break;
case FILE_DLG:
if (!WriteDlg(hfWrite, szSrcFile))
goto CloseAndExit;
break;
case FILE_INC:
if (!WriteInc(hfWrite))
goto CloseAndExit;
break;
}
CloseHandle((HANDLE)hfWrite);
DeleteFile(szSrcFile);
if (!MoveFile(szTempFile, szSrcFile)) {
DeleteFile(szTempFile);
goto Exit;
}
fSuccess = TRUE;
/*
* If we just wrote to the include file, read it to get the new
* file offsets, etc.
*/
if (fmt == FILE_INC) {
if (!OpenIncludeFile(szSrcFile))
fSuccess = FALSE;
}
Exit:
SetCursor(hcurSave);
return fSuccess;
CloseAndExit:
CloseHandle(hfWrite);
DeleteFile(szTempFile);
SetCursor(hcurSave);
return fSuccess;
}
/************************************************************************
* FormTempFileName
*
* This function forms a temporary file name in the provided string.
* The provided string is assumed to have been filled with a filename
* that includes a path. The temp file will be created in the same
* directory as the file that is currently in the string.
*
* Arguments:
* LPTSTR pszBaseName - The base name (a filename that includes a path).
* LPTSTR pszBuffer - Where to return the
*
************************************************************************/
STATICFN VOID FormTempFileName(
LPTSTR pszBaseName,
LPTSTR pszBuffer)
{
TCHAR szBuffer[CCHMAXPATH];
LPTSTR psz;
/*
* Cut the base file name down to just the path portion.
*/
lstrcpy(szBuffer, pszBaseName);
psz = FileInPath(szBuffer);
psz--;
*psz = TEXT('\0');
/*
* Create a temporary file in the same directory.
*/
GetTempFileName(szBuffer, L"dlg", 0, pszBuffer);
}
/************************************************************************
* FileInPath
*
* This function takes a path and returns a pointer to the file name
* portion of it. For instance, it will return a pointer to
* "abc.res" if it is given the following path: "c:\windows\abc.res".
*
* Arguments:
* LPTSTR pszPath - Path to look through.
*
************************************************************************/
LPTSTR FileInPath(
LPTSTR pszPath)
{
LPTSTR psz;
psz = pszPath + lstrlen(pszPath);
while (psz > pszPath) {
psz--;
if (*psz == CHAR_BACKSLASH || *psz == CHAR_COLON) {
psz++;
break;
}
}
return psz;
}
/************************************************************************
* FileCat
*
* This function puts the extension pchCat on the file spec pch.
* If fChop, this is done regardless of whether pch has an extension
* or not (replacing the old extension). Otherwise, pchCat is added
* only if there is no extension on the spec pch.
*
* Arguments:
* LPTSTR pch - The file spec to "cat" the extension to.
* LPTSTR pchCat - The extension to "cat" on to pch,
* including the '.'
*
************************************************************************/
STATICFN VOID FileCat(
LPTSTR pchName,
LPTSTR pchCat,
BOOL fChop)
{
LPTSTR pch;
pch = pchName + lstrlen(pchName);
pch--;
/* back up to '.' or '\\' */
while (*pch != CHAR_DOT) {
if (*pch == CHAR_BACKSLASH || pch <= pchName) {
/* no extension, add one */
lstrcat(pchName, pchCat);
return;
}
pch--;
}
if (fChop)
lstrcpy(pch, pchCat);
}
/************************************************************************
* ShowFileStatus
*
* This function displays the title of the Dialog Editor, along with
* the file names for the RES and H files with asterisks if they have
* changed. It displays this information only if one of these items
* has changed or if fForce is TRUE.
*
* Arguments:
* BOOL fForce - TRUE if the title should be updated even if the value
* of gfResChged or gfIncChged has not changed since the
* last call. This function should be called with fForce
* equal to TRUE if it is known that one of the file names
* has just been changed.
*
************************************************************************/
VOID ShowFileStatus(
BOOL fForce)
{
static BOOL fResChgedSave = FALSE;
static BOOL fIncChgedSave = FALSE;
TCHAR szTitle[CCHTEXTMAX];
if (gfResChged != fResChgedSave || gfIncChged != fIncChgedSave ||
fForce) {
lstrcpy(szTitle, ids(IDS_DLGEDIT));
lstrcat(szTitle, L" - ");
lstrcat(szTitle, pszResFile ? pszResFile : ids(IDS_UNTITLED));
if (gfResChged)
lstrcat(szTitle, L"*");
lstrcat(szTitle, L", ");
lstrcat(szTitle, pszIncludeFile ? pszIncludeFile : ids(IDS_UNTITLED));
if (gfIncChged)
lstrcat(szTitle, L"*");
SetWindowText(ghwndMain, szTitle);
fResChgedSave = gfResChged;
fIncChgedSave = gfIncChged;
}
}
/************************************************************************
* DifferentDirs
*
* This function returns TRUE if the given full paths are to files
* that are in different directories.
*
* Arguments:
* LPTSTR pszPath1 - First path.
* LPTSTR pszPath2 - Second path.
*
************************************************************************/
BOOL DifferentDirs(
LPTSTR pszPath1,
LPTSTR pszPath2)
{
INT nLen1;
INT nLen2;
LPTSTR pszFile1;
LPTSTR pszFile2;
pszFile1 = FileInPath(pszPath1);
pszFile2 = FileInPath(pszPath2);
nLen1 = lstrlen(pszPath1) - lstrlen(pszFile1);
nLen2 = lstrlen(pszPath2) - lstrlen(pszFile2);
if (nLen1 != nLen2 || _wcsnicmp(pszPath1, pszPath2, nLen1) != 0)
return TRUE;
else
return FALSE;
}
/************************************************************************
* HasPath
*
* This function returns TRUE if the given filespec includes a path
* specification. It returns false if it is a filename without a
* path.
*
* A filespec is considered to have a path if a backslash character (\)
* is found in it.
*
* Arguments:
* LPTSTR pszFileSpec - File spec to check.
*
************************************************************************/
BOOL HasPath(
LPTSTR pszFileSpec)
{
LPTSTR psz;
for (psz = pszFileSpec; *psz; psz = CharNext(psz))
if (*psz == CHAR_BACKSLASH)
return TRUE;
return FALSE;
}
/************************************************************************
* WriteDWordPad
*
* This function writes nulls to the specified file until it is
* dword aligned. If the file is already dword aligned, nothing
* will be written.
*
* Arguments:
* HANDLE hf - The file to write to.
* DWORD cbFile - Where the file pointer is at in the file.
*
* Returns:
* TRUE if successful, FALSE otherwise.
*
************************************************************************/
BOOL WriteDWordPad(
HANDLE hf,
DWORD cbFile)
{
static BYTE Buf[3] = {0, 0, 0};
WORD cb;
cb = (WORD)((4 - (((WORD)cbFile) & 3)) % 4);
if (cb) {
if (_lwrite((HFILE)hf, (LPSTR)Buf, cb) == -1)
return FALSE;
}
return TRUE;
}