Fix up some file handling, add support for initializing a house file

This commit is contained in:
elasota
2020-01-03 00:13:41 -05:00
parent e00f506ee2
commit 32116bc17e
19 changed files with 708 additions and 475 deletions

View File

@@ -11,11 +11,14 @@
#include "PLPasStr.h"
#include "PLResources.h"
#include "PLSound.h"
#include "PLSysCalls.h"
#include "DialogUtils.h"
#include "Externs.h"
#include "FileManager.h"
#include "HostFileSystem.h"
#include "House.h"
#include "RectUtils.h"
#include "ResourceManager.h"
#define kGoToDialogID 1043
@@ -51,32 +54,23 @@ Boolean CreateNewHouse (void)
AEKeyword theKeyword;
DescType actualType;
Size actualSize;
NavReplyRecord theReply;
NavDialogOptions dialogOptions;
VFileSpec tempSpec;
VFileSpec theSpec;
PLError_t theErr;
theErr = NavGetDefaultDialogOptions(&dialogOptions);
theErr = NavPutFile(nil, &theReply, &dialogOptions, nil, 'gliH', 'ozm5', nil);
if (theErr == PLErrors::kUserCancelled_TEMP)
return false;
if (!theReply.validRecord)
return (false);
theErr = AEGetNthPtr(&(theReply.selection), 1, typeFSS, &theKeyword,
&actualType, &theSpec, sizeof(VFileSpec), &actualSize);
PortabilityLayer::FileManager *fm = PortabilityLayer::FileManager::GetInstance();
if (theReply.replacing)
{
theSpec.m_dir = PortabilityLayer::VirtualDirectories::kUserData;
PasStringCopy(PSTR("My House"), theSpec.m_name);
char savePath[sizeof(theSpec.m_name) + 1];
size_t savePathLength = 0;
if (!fm->PromptSaveFile(theSpec.m_dir, savePath, savePathLength, sizeof(theSpec.m_name), PSTR("My House")))
return false;
if (fm->FileExists(theSpec.m_dir, theSpec.m_name))
{
CheckFileError(PLErrors::kFileNotFound, theSpec.m_name);
return (false);
}
if (!fm->DeleteFile(theSpec.m_dir, theSpec.m_name))
{
CheckFileError(PLErrors::kAccessDenied, theSpec.m_name);
@@ -94,7 +88,7 @@ Boolean CreateNewHouse (void)
if (!CheckFileError(theErr, PSTR("New House")))
return (false);
theErr = HCreateResFile(theSpec.m_dir, theSpec.m_name);
theErr = PortabilityLayer::ResourceManager::GetInstance()->CreateBlankResFile(theSpec.m_dir, theSpec.m_name);
if (theErr != PLErrors::kNone)
YellowAlert(kYellowFailedResCreate, theErr);

View File

@@ -572,8 +572,9 @@ void DoDirSearch (void)
for (i = 0; i < kMaxDirectories; i++)
theDirs[i] = PortabilityLayer::VirtualDirectories::kUnspecified;
currentDir = 0;
theDirs[currentDir] = PortabilityLayer::VirtualDirectories::kGameData;
numDirs = 1;
theDirs[0] = PortabilityLayer::VirtualDirectories::kGameData;
theDirs[1] = PortabilityLayer::VirtualDirectories::kUserData;
numDirs = 2;
PortabilityLayer::FileManager *fm = PortabilityLayer::FileManager::GetInstance();

View File

@@ -0,0 +1,15 @@
#pragma once
namespace GpFileCreationDispositions
{
enum GpFileCreationDisposition
{
kCreateOrOverwrite, // If exists: Overwrite. If not exists: Create.
kCreateNew, // If exists: Fail. If not exists: Create.
kCreateOrOpen, // If exists: Open. If not exists: Create.
kOpenExisting, // If exists: Open. If not exists: Fail.
kOverwriteExisting, // If exists: Overwrite. If not exists: Fail.
};
}
typedef GpFileCreationDispositions::GpFileCreationDisposition GpFileCreationDisposition_t;

View File

@@ -7,6 +7,8 @@
#include <Windows.h>
#undef CreateMutex
#undef DeleteFile
struct IGpFiber;
struct IGpColorCursor_Win32;

View File

@@ -170,6 +170,7 @@
<ClInclude Include="..\GpCommon\EGpInputDriverType.h" />
<ClInclude Include="..\GpCommon\EGpStandardCursor.h" />
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h" />
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h" />
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h" />
<ClInclude Include="..\GpCommon\IGpColorCursor.h" />
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />

View File

@@ -194,6 +194,9 @@
<ClInclude Include="..\GpCommon\GpDisplayDriverTickStatus.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpFileCreationDisposition.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="GpD3D.rc">

View File

@@ -7,6 +7,8 @@
#include <string>
#include <Shlwapi.h>
#include <ShlObj.h>
#include <commdlg.h>
#include <assert.h>
class GpDirectoryCursor_Win32 final : public PortabilityLayer::HostDirectoryCursor
@@ -112,12 +114,17 @@ GpFileSystem_Win32::GpFileSystem_Win32()
}
m_prefsDir.append(L"\\GlidePort");
m_userHousesDir = m_prefsDir + L"\\Houses";
m_scoresDir = m_prefsDir + L"\\Scores";
CreateDirectoryW(m_prefsDir.c_str(), nullptr);
CreateDirectoryW(m_scoresDir.c_str(), nullptr);
CreateDirectoryW(m_userHousesDir.c_str(), nullptr);
m_prefsDir.append(L"\\");
m_scoresDir.append(L"\\");
m_userHousesDir.append(L"\\");
}
DWORD modulePathSize = GetModuleFileNameW(nullptr, m_executablePath, MAX_PATH);
@@ -192,7 +199,7 @@ bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtual
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
}
PortabilityLayer::IOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, bool create)
PortabilityLayer::IOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition)
{
wchar_t winPath[MAX_PATH + 1];
@@ -200,15 +207,58 @@ PortabilityLayer::IOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::Virtu
return false;
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
const DWORD creationDisposition = create ? OPEN_ALWAYS : OPEN_EXISTING;
DWORD winCreationDisposition = 0;
HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, creationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
switch (createDisposition)
{
case GpFileCreationDispositions::kCreateOrOverwrite:
winCreationDisposition = CREATE_ALWAYS;
break;
case GpFileCreationDispositions::kCreateNew:
winCreationDisposition = CREATE_NEW;
break;
case GpFileCreationDispositions::kCreateOrOpen:
winCreationDisposition = OPEN_ALWAYS;
break;
case GpFileCreationDispositions::kOpenExisting:
winCreationDisposition = OPEN_EXISTING;
break;
case GpFileCreationDispositions::kOverwriteExisting:
winCreationDisposition = TRUNCATE_EXISTING;
break;
default:
return false;
}
HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, winCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
if (h == INVALID_HANDLE_VALUE)
return false;
return new GpFileStream_Win32(h, true, writeAccess, true);
}
bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
return false;
if (DeleteFileW(winPath))
{
existed = true;
return true;
}
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND)
existed = false;
else
existed = true;
return false;
}
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory)
{
wchar_t winPath[MAX_PATH + 2];
@@ -225,6 +275,118 @@ PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(Portabi
return GpDirectoryCursor_Win32::Create(ff, findData);
}
bool GpFileSystem_Win32::PromptSaveFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName)
{
wchar_t baseFN[MAX_PATH + 5];
wchar_t baseDir[MAX_PATH + 5];
const size_t existingPathLen = strlen(initialFileName);
if (existingPathLen >= MAX_PATH)
return false;
for (size_t i = 0; i < existingPathLen; i++)
baseFN[i] = static_cast<wchar_t>(initialFileName[i]);
baseFN[existingPathLen] = 0;
if (!ResolvePath(virtualDirectory, "", baseDir))
return false;
OPENFILENAMEW ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFilter = L"GlidePort File (*.gpf)\0*.gpf\0";
ofn.lpstrFile = baseFN;
ofn.lpstrDefExt = L"gpf";
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = baseDir;
ofn.Flags = OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
if (!GetSaveFileNameW(&ofn))
return false;
if (ofn.Flags & OFN_EXTENSIONDIFFERENT)
{
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, L"Save file failed: Saved files must have the '.gpf' extension", L"Invalid file path", MB_OK);
return false;
}
const wchar_t *fn = ofn.lpstrFile + ofn.nFileOffset;
size_t fnLengthWithoutExt = wcslen(fn);
if (ofn.nFileExtension - 1 > ofn.nFileOffset) // Off by 1 because extension doesn't include .
fnLengthWithoutExt = ofn.nFileExtension - ofn.nFileOffset - 1;
if (fnLengthWithoutExt >= pathCapacity)
{
wchar_t msg[256];
wsprintfW(msg, L"Save file failed: File name is too long. Limit is %i characters.", static_cast<int>(pathCapacity));
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, msg, L"Invalid file path", MB_OK);
return false;
}
if (ofn.nFileOffset != wcslen(baseDir) || memcmp(ofn.lpstrFile, baseDir, ofn.nFileOffset * sizeof(wchar_t)))
{
wchar_t msg[256 + MAX_PATH];
wsprintfW(msg, L"Save file failed: File can't be saved here, it must be saved in %s", baseDir);
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, msg, L"Invalid file path", MB_OK);
return false;
}
const wchar_t *unsupportedCharMsg = L"File name contains unsupported characters.";
for (size_t i = 0; i < fnLengthWithoutExt; i++)
{
if (fn[i] < static_cast<wchar_t>(0) || fn[i] >= static_cast<wchar_t>(128))
{
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, unsupportedCharMsg, L"Invalid file path", MB_OK);
return false;
}
path[i] = static_cast<char>(fn[i]);
}
if (!ValidateFilePath(path, fnLengthWithoutExt))
{
MessageBeep(MB_ICONERROR);
MessageBoxW(nullptr, unsupportedCharMsg, L"Invalid file path", MB_OK);
return false;
}
outPathLength = fnLengthWithoutExt;
return true;
}
bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
{
for (size_t i = 0; i < length; i++)
{
const char c = str[i];
if (c >= '0' && c <= '9')
continue;
if (c == '_' || c == '.' || c == '\'')
continue;
if (c == ' ' && i != 0 && i != length - 1)
continue;
if (c >= 'a' && c <= 'z')
continue;
if (c >= 'A' && c <= 'Z')
continue;
return false;
}
return true;
}
const wchar_t *GpFileSystem_Win32::GetBasePath() const
{
return m_executablePath;
@@ -247,6 +409,9 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
case PortabilityLayer::VirtualDirectories::kGameData:
baseDir = m_housesDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kUserData:
baseDir = m_userHousesDir.c_str();
break;
case PortabilityLayer::VirtualDirectories::kPrefs:
baseDir = m_prefsDir.c_str();
break;

View File

@@ -14,9 +14,14 @@ public:
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
PortabilityLayer::IOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, bool create) override;
PortabilityLayer::IOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override;
bool PromptSaveFile(PortabilityLayer::VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName) override;
bool ValidateFilePath(const char *path, size_t sz) const override;
const wchar_t *GetBasePath() const;
static GpFileSystem_Win32 *GetInstance();
@@ -28,6 +33,7 @@ private:
std::wstring m_scoresDir;
std::wstring m_packagedDir;
std::wstring m_housesDir;
std::wstring m_userHousesDir;
std::wstring m_resourcesDir;
wchar_t m_executablePath[MAX_PATH];

View File

@@ -29,8 +29,10 @@ namespace PortabilityLayer
PLError_t OpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, IOStream *&outRefNum) override;
bool ReadFileProperties(VirtualDirectory_t dirID, const PLPasStr &filename, MacFileProperties &properties) override;
PLError_t RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream *&outStream) override;
PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream *&outStream) override;
PLError_t RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t creationDisposition, IOStream *&outStream) override;
PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t creationDisposition, IOStream *&outStream) override;
bool PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName) override;
static FileManagerImpl *GetInstance();
@@ -38,7 +40,7 @@ namespace PortabilityLayer
typedef char ExtendedFileName_t[64 + 4];
PLError_t OpenFileFork(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext, EFilePermission permission, IOStream *&outRefNum);
PLError_t RawOpenFileFork(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext, EFilePermission permission, bool ignoreMeta, bool create, IOStream *&outStream);
PLError_t RawOpenFileFork(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext, EFilePermission permission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream);
static bool ConstructFilename(ExtendedFileName_t& extFN, const PLPasStr &fn, const char *extension);
@@ -74,13 +76,29 @@ namespace PortabilityLayer
bool FileManagerImpl::DeleteFile(VirtualDirectory_t dirID, const PLPasStr &filename)
{
ExtendedFileName_t extFN;
if (!ConstructFilename(extFN, filename, ".gpf"))
return false;
const size_t numExts = 3;
// PL_NotYetImplemented_TODO("FileSystem")
const char *exts[numExts] = { ".gpr", ".gpd", ".gpf" };
const bool extMayNotExist[numExts] = { true, true, false };
for (int extIndex = 0; extIndex < numExts; extIndex++)
{
ExtendedFileName_t extFN;
if (!ConstructFilename(extFN, filename, exts[extIndex]))
return true;
bool existed = false;
if (!PortabilityLayer::HostFileSystem::GetInstance()->DeleteFile(dirID, extFN, existed))
{
if (extMayNotExist[extIndex] && !existed)
continue;
else
return false;
}
}
return true;
}
PLError_t FileManagerImpl::CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp)
{
@@ -92,7 +110,7 @@ namespace PortabilityLayer
return PLErrors::kBadFileName;
IOStream *stream = nullptr;
PLError_t err = RawOpenFileFork(dirID, filename, ".gpf", EFilePermission_Write, true, true, stream);
PLError_t err = RawOpenFileFork(dirID, filename, ".gpf", EFilePermission_Write, true, GpFileCreationDispositions::kCreateOrOverwrite, stream);
if (err)
return err;
@@ -130,7 +148,7 @@ namespace PortabilityLayer
bool FileManagerImpl::ReadFileProperties(VirtualDirectory_t dirID, const PLPasStr &filename, MacFileProperties &properties)
{
IOStream *stream = nullptr;
PLError_t err = RawOpenFileFork(dirID, filename, ".gpf", EFilePermission_Read, true, false, stream);
PLError_t err = RawOpenFileFork(dirID, filename, ".gpf", EFilePermission_Read, true, GpFileCreationDispositions::kOpenExisting, stream);
if (err)
return false;
@@ -144,14 +162,23 @@ namespace PortabilityLayer
return readOk;
}
PLError_t FileManagerImpl::RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission permission, bool ignoreMeta, IOStream *&outStream)
PLError_t FileManagerImpl::RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission permission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream)
{
return RawOpenFileFork(dirID, filename, ".gpd", permission, ignoreMeta, false, outStream);
return RawOpenFileFork(dirID, filename, ".gpd", permission, ignoreMeta, createDisposition, outStream);
}
PLError_t FileManagerImpl::RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission permission, bool ignoreMeta, IOStream *&outStream)
PLError_t FileManagerImpl::RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission permission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream)
{
return RawOpenFileFork(dirID, filename, ".gpr", permission, ignoreMeta, false, outStream);
return RawOpenFileFork(dirID, filename, ".gpr", permission, ignoreMeta, createDisposition, outStream);
}
bool FileManagerImpl::PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName)
{
ExtendedFileName_t extFN;
if (!ConstructFilename(extFN, initialFileName, ""))
return false;
return PortabilityLayer::HostFileSystem::GetInstance()->PromptSaveFile(dirID, path, outPathLength, pathCapacity, extFN);
}
FileManagerImpl *FileManagerImpl::GetInstance()
@@ -162,8 +189,9 @@ namespace PortabilityLayer
PLError_t FileManagerImpl::OpenFileFork(VirtualDirectory_t dirID, const PLPasStr &filename, const char *extension, EFilePermission permission, IOStream *&outStream)
{
bool isWriteAccess = (permission == EFilePermission_Any || permission == EFilePermission_ReadWrite || permission == EFilePermission_Write);
GpFileCreationDisposition_t createDisposition = isWriteAccess ? GpFileCreationDispositions::kCreateOrOpen : GpFileCreationDispositions::kOpenExisting;
IOStream *stream = nullptr;
PLError_t openError = RawOpenFileFork(dirID, filename, extension, permission, false, isWriteAccess, stream);
PLError_t openError = RawOpenFileFork(dirID, filename, extension, permission, false, createDisposition, stream);
if (openError != PLErrors::kNone)
return openError;
@@ -172,7 +200,7 @@ namespace PortabilityLayer
return PLErrors::kNone;
}
PLError_t FileManagerImpl::RawOpenFileFork(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext, EFilePermission permission, bool ignoreMeta, bool create, IOStream *&outStream)
PLError_t FileManagerImpl::RawOpenFileFork(VirtualDirectory_t dirID, const PLPasStr &filename, const char *ext, EFilePermission permission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream)
{
ExtendedFileName_t gpfExtFN;
ExtendedFileName_t extFN;
@@ -192,27 +220,25 @@ namespace PortabilityLayer
if (!ConstructFilename(extFN, filename, ext))
return PLErrors::kBadFileName;
const bool needToCreate = create && !HostFileSystem::GetInstance()->FileExists(dirID, extFN);
IOStream *fstream = nullptr;
switch (permission)
{
case EFilePermission_Any:
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, true, needToCreate);
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, true, createDisposition);
if (fstream)
permission = EFilePermission_ReadWrite;
else
{
permission = EFilePermission_Read;
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, false, needToCreate);
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, false, createDisposition);
}
break;
case EFilePermission_Read:
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, false, needToCreate);
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, false, createDisposition);
break;
case EFilePermission_ReadWrite:
case EFilePermission_Write:
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, true, needToCreate);
fstream = HostFileSystem::GetInstance()->OpenFile(dirID, extFN, true, createDisposition);
break;
}
@@ -233,26 +259,8 @@ namespace PortabilityLayer
memcpy(extFN, fn.Chars(), fnameSize);
memcpy(extFN + fnameSize, extension, strlen(extension) + 1);
for (size_t i = 0; i < fnameSize; i++)
{
const char c = extFN[i];
if (c >= '0' && c <= '9')
continue;
if (c == '_' || c == '.' || c == '\'')
continue;
if (c == ' ' && i != 0 && i != fnameSize - 1)
continue;
if (c >= 'a' && c <= 'z')
continue;
if (c >= 'A' && c <= 'Z')
continue;
if (!PortabilityLayer::HostFileSystem::GetInstance()->ValidateFilePath(extFN, fnameSize))
return false;
}
return true;
}

View File

@@ -3,6 +3,7 @@
#include "FilePermission.h"
#include "CoreDefs.h"
#include "FilePos.h"
#include "GpFileCreationDisposition.h"
#include "PLErrorCodes.h"
#include "VirtualDirectory.h"
@@ -26,12 +27,15 @@ namespace PortabilityLayer
virtual PLError_t CreateFile(VirtualDirectory_t dirID, const PLPasStr &filename, const MacFileProperties &mfp) = 0;
virtual PLError_t CreateFileAtCurrentTime(VirtualDirectory_t dirID, const PLPasStr &filename, const ResTypeID &fileCreator, const ResTypeID &fileType) = 0;
// OpenFileData + OpenFileResources require that the file already exists (i.e. has a .gpf), but the fork may not
virtual PLError_t OpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, IOStream *&outStream) = 0;
virtual PLError_t OpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, IOStream *&outStream) = 0;
virtual bool ReadFileProperties(VirtualDirectory_t dirID, const PLPasStr &filename, MacFileProperties &properties) = 0;
virtual PLError_t RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream *&outStream) = 0;
virtual PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream *&outStream) = 0;
virtual PLError_t RawOpenFileData(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream) = 0;
virtual PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream) = 0;
virtual bool PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName) = 0;
static FileManager *GetInstance();
};

View File

@@ -11,7 +11,7 @@ namespace PortabilityLayer
{
void FontFamily::AddFont(int flags, const char *path, FontHacks fontHacks)
{
PortabilityLayer::IOStream *sysFontStream = PortabilityLayer::HostFileSystem::GetInstance()->OpenFile(PortabilityLayer::VirtualDirectories::kFonts, path, false, false);
PortabilityLayer::IOStream *sysFontStream = PortabilityLayer::HostFileSystem::GetInstance()->OpenFile(PortabilityLayer::VirtualDirectories::kFonts, path, false, GpFileCreationDispositions::kOpenExisting);
if (!sysFontStream)
return;

View File

@@ -1,7 +1,10 @@
#pragma once
#include "GpFileCreationDisposition.h"
#include "VirtualDirectory.h"
#include <stdint.h>
namespace PortabilityLayer
{
class IOStream;
@@ -12,9 +15,13 @@ namespace PortabilityLayer
public:
virtual bool FileExists(VirtualDirectory_t virtualDirectory, const char *path) = 0;
virtual bool FileLocked(VirtualDirectory_t virtualDirectory, const char *path, bool *exists) = 0;
virtual IOStream *OpenFile(VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, bool create) = 0;
virtual IOStream *OpenFile(VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) = 0;
virtual bool DeleteFile(VirtualDirectory_t virtualDirectory, const char *path, bool &existed) = 0;
virtual HostDirectoryCursor *ScanDirectory(VirtualDirectory_t virtualDirectory) = 0;
virtual bool PromptSaveFile(VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName) = 0;
virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0;
static HostFileSystem *GetInstance();
static void SetInstance(HostFileSystem *instance);

View File

@@ -366,6 +366,8 @@ namespace PortabilityLayer
m_firstMenu = insertingMenu;
existingMenuPtr->prevMenu = insertingMenu;
DrawMenuBar();
}
void MenuManagerImpl::InsertMenuAfter(const THandle<Menu> &insertingMenu, const THandle<Menu> &existingMenu)
@@ -384,6 +386,8 @@ namespace PortabilityLayer
m_lastMenu = insertingMenu;
existingMenuPtr->nextMenu = insertingMenu;
DrawMenuBar();
}
void MenuManagerImpl::InsertMenuAtEnd(const THandle<Menu> &insertingMenu)
@@ -399,6 +403,8 @@ namespace PortabilityLayer
(*m_lastMenu)->nextMenu = insertingMenu;
(*insertingMenu)->prevMenu = m_lastMenu;
m_lastMenu = insertingMenu;
DrawMenuBar();
}
void MenuManagerImpl::InsertMenuAtBeginning(const THandle<Menu> &insertingMenu)
@@ -414,12 +420,12 @@ namespace PortabilityLayer
(*m_firstMenu)->prevMenu = insertingMenu;
(*insertingMenu)->nextMenu = m_firstMenu;
m_firstMenu = insertingMenu;
DrawMenuBar();
}
void MenuManagerImpl::RemoveMenu(const THandle<Menu> &menu)
{
DrawMenuBar();
Menu *menuPtr = *menu;
if (menuPtr->stringBlobHandle)
PortabilityLayer::MemoryManager::GetInstance()->ReleaseHandle(menuPtr->stringBlobHandle);
@@ -446,6 +452,8 @@ namespace PortabilityLayer
Menu *menu = *menuHandle;
menu->enabled = enabled;
DrawMenuBar();
}
void MenuManagerImpl::SetItemEnabled(const THandle<Menu> &menuHandle, unsigned int index, bool enabled)
@@ -456,6 +464,8 @@ namespace PortabilityLayer
return;
menu->menuItems[index].enabled = enabled;
DrawMenuBar();
}
void MenuManagerImpl::SetItemChecked(const THandle<Menu> &menuHandle, unsigned int index, bool checked)
@@ -473,7 +483,6 @@ namespace PortabilityLayer
return point.m_y >= 0 && static_cast<uint32_t>(point.m_y) < kMenuBarHeight;
}
void MenuManagerImpl::MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem)
{
RefreshMenuBarLayout();

View File

@@ -540,7 +540,7 @@ DirectoryFileListEntry *GetDirectoryFiles(PortabilityLayer::VirtualDirectory_t d
if (!strcmp(&filename[fnLen - 4], ".gpf"))
{
const size_t dotPos = fnLen - 4;
PortabilityLayer::IOStream *stream = fs->OpenFile(dirID, filename, false, false);
PortabilityLayer::IOStream *stream = fs->OpenFile(dirID, filename, false, GpFileCreationDispositions::kOpenExisting);
if (!stream)
continue;

View File

@@ -32,6 +32,7 @@ namespace PortabilityLayer
short OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
void CloseResFile(short ref) override;
PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
THandle<void> GetResource(const ResTypeID &resType, int id) override;
@@ -161,7 +162,7 @@ namespace PortabilityLayer
return -1;
IOStream *fStream = nullptr;
if (FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Read, true, fStream) != PLErrors::kNone)
if (FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Read, true, GpFileCreationDispositions::kOpenExisting, fStream) != PLErrors::kNone)
return -1;
ResourceFile *resFile = new ResourceFile();
@@ -224,6 +225,29 @@ namespace PortabilityLayer
m_currentResFile = m_lastResFile;
}
PLError_t ResourceManagerImpl::CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename)
{
const uint8_t blankResFileData[] = {
0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 30,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 30, 255, 255 };
PortabilityLayer::IOStream *stream = nullptr;
PLError_t error = FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Write, true, GpFileCreationDispositions::kCreateOrOverwrite, stream);
if (error)
return error;
if (stream->Write(blankResFileData, sizeof(blankResFileData)) != sizeof(blankResFileData))
{
stream->Close();
return PLErrors::kIOError;
}
stream->Close();
return PLErrors::kNone;
}
THandle<void> ResourceManagerImpl::GetResource(const ResTypeID &resType, int id)
{
short searchIndex = m_currentResFile;

View File

@@ -45,12 +45,6 @@ int Count1Resources(UInt32 resType)
return 0;
}
PLError_t HCreateResFile(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &name)
{
PL_NotYetImplemented();
return PLErrors::kNone;
}
void SetResLoad(Boolean load)
{
PortabilityLayer::ResourceManager::GetInstance()->SetResLoad(load != 0);

View File

@@ -13,8 +13,6 @@ Handle Get1Resource(UInt32 resID, int index);
Handle Get1IndResource(UInt32 resID, int index);
int Count1Resources(UInt32 resType);
PLError_t HCreateResFile(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &name);
void SetResLoad(Boolean load); // Sets whether resources should be loaded when requested
long GetMaxResourceSize(Handle res);

View File

@@ -1,6 +1,7 @@
#pragma once
#include "VirtualDirectory.h"
#include "PLErrorCodes.h"
#include "PLHandle.h"
class PLPasStr;
@@ -21,6 +22,7 @@ namespace PortabilityLayer
virtual short OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0;
virtual void CloseResFile(short ref) = 0;
virtual PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0;
virtual THandle<void> GetResource(const ResTypeID &resType, int id) = 0;