/******************************************************************** WRAPSTOR.CPP Owner: ErinFox Created: 28-Feb-1997 Description: This file contains file system calls that are wrapped with the InfoTech IStorage implementation *********************************************************************/ // For IStorage support #define INITGUID #include #include #include #include // InfoTech includes #include #include <_mvutil.h> #include #include "iofts.h" // DOSFILE support #include #include #include #include #define RESERVED 0 // I "borrowed" these from Tome code #define PLI_To_PFO(PLI) ((FILEOFFSET *) PLI) #define LI_To_FO(LI) (*PLI_To_PFO(&LI)) #define PFO_To_PLI(PFO) ((LARGE_INTEGER *) PFO) #define FO_To_LI(FO) (*PFO_To_PLI(&FO)) // was in iofts.c #ifdef _DEBUG static char s_aszModule[] = __FILE__; // Used by error return functions. #endif // was in iofts.c #define OPENED_HFS (BYTE)0x80 // was in iofts.c PRIVATE HANDLE NEAR PASCAL IoftsWin32Create(LPCSTR lpstr, DWORD w); PRIVATE HANDLE NEAR PASCAL IoftsWin32Open(LPCSTR lpstr, DWORD w); // was in iofts.c #define CREAT(sz, w) IoftsWin32Create(sz, w) #define OPEN(sz, w) IoftsWin32Open(sz, w) // // These functions came from subfile.c // PUBLIC HF PASCAL FAR EXPORT_API HfOpenHfs(HFS hfs, LPCWSTR wsz, BYTE bFlags, LPERRB lperrb) { HF hf; DWORD grfMode; HRESULT hr; // TODO: find out how big this really should be // OLECHAR wsz[_MAX_PATH]; // MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sz, -1, wsz, _MAX_PATH); if (bFlags & HFOPEN_READWRITE) grfMode = STGM_READWRITE; else if (bFlags & HFOPEN_READ) grfMode = STGM_READ; if (!(bFlags & HFOPEN_CREATE)) { hr = hfs->OpenStream(wsz, NULL, grfMode, RESERVED, &hf); } else { hr = hfs->CreateStream(wsz, grfMode, RESERVED, RESERVED, &hf); } // make sure we pass back a NULL if open/create failed if (!SUCCEEDED(hr)) hf = NULL; // sometimes we get passed NULL for lperrb if (lperrb) *lperrb = hr; return hf; } PUBLIC HF PASCAL FAR EXPORT_API HfCreateFileHfs(HFS hfs, LPCSTR sz, BYTE bFlags, LPERRB lperrb) { HF hf; DWORD grfMode; HRESULT hr; // TODO: find out how big this really should be OLECHAR wsz[_MAX_PATH]; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sz, -1, wsz, _MAX_PATH); if (bFlags & HFOPEN_READWRITE) grfMode = STGM_READWRITE; else if (bFlags & HFOPEN_READ) grfMode = STGM_READ; hr = hfs->CreateStream(wsz, grfMode, RESERVED, RESERVED, &hf); // make sure we pass back NULL if failure if (!SUCCEEDED(hr)) hf = NULL; if (lperrb) *lperrb = hr; return hf; } // This is currently the same as HfOpenHfs, but once we have Ron's // enhancements to Tome we will be able to set the size on the file PUBLIC HF PASCAL FAR EXPORT_API HfOpenHfsReserve(HFS hfs, LPCSTR sz, BYTE bFlags, FILEOFFSET foReserve, LPERRB lperrb) { HF hf; DWORD grfMode; HRESULT hr; // TODO: find out how big this really should be OLECHAR wsz[_MAX_PATH]; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sz, -1, wsz, _MAX_PATH); if (bFlags & HFOPEN_READWRITE) grfMode = STGM_READWRITE; else if (bFlags & HFOPEN_READ) grfMode = STGM_READ; if (!(bFlags & HFOPEN_CREATE)) { hr = hfs->OpenStream(wsz, NULL, grfMode, RESERVED, &hf); } else { hr = hfs->CreateStream(wsz, grfMode, RESERVED, RESERVED, &hf); } if (!SUCCEEDED(hr)) hf = NULL; if (lperrb) *lperrb = hr; return hf; } PUBLIC LONG PASCAL FAR EXPORT_API LcbReadHf(HF hf, LPVOID lpvBuffer, LONG lcb, LPERRB lperrb) { ULONG cbRead; HRESULT hr; hr = hf->Read(lpvBuffer, lcb, &cbRead); if (lperrb) *lperrb = hr; return cbRead; } PUBLIC LONG PASCAL FAR EXPORT_API LcbWriteHf(HF hf, LPVOID lpvBuffer, LONG lcb, LPERRB lperrb) { ULONG cbWrote; HRESULT hr; hr = hf->Write(lpvBuffer, lcb, &cbWrote); if (lperrb) *lperrb = hr; return cbWrote; } PUBLIC FILEOFFSET PASCAL FAR EXPORT_API FoSeekHf(HF hf, FILEOFFSET foOffset, WORD wOrigin, LPERRB lperrb) { HRESULT hr; ULARGE_INTEGER liNewPos; LARGE_INTEGER liOffset = FO_To_LI(foOffset); hr = hf->Seek(liOffset, (DWORD)wOrigin, &liNewPos); if (lperrb) *lperrb = hr; return LI_To_FO(liNewPos); } PUBLIC RC PASCAL FAR EXPORT_API RcCloseHf(HF hf) { if (hf) hf->Release(); return S_OK; } PUBLIC BOOL PASCAL FAR EXPORT_API FAccessHfs( HFS hfs, LPCSTR szName, BYTE bFlags, LPERRB lperrb) { HRESULT hr; HF hf = NULL; BOOL fRet = FALSE; if (lperrb) *lperrb = S_OK; // for now // TODO: find out how big this really should be OLECHAR wszName[_MAX_PATH]; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szName, -1, wszName, _MAX_PATH); hr = hfs->OpenStream(wszName, NULL, STGM_READWRITE, RESERVED, &hf); if (S_OK == hr) { if (bFlags & FACCESS_EXISTS) fRet = TRUE; } else if (STG_E_FILENOTFOUND == hr) { SetErrCode (lperrb, E_FILENOTFOUND); } // else // { // Need to set error if anything but NOTFOUND // } if (hf) hf->Release(); return fRet; } PUBLIC FILEOFFSET PASCAL FAR EXPORT_API FoSizeHf(HF hf, LPERRB lperrb) { STATSTG stat; HRESULT hr; FILEOFFSET foSize; hr = hf->Stat(&stat, STATFLAG_NONAME); if (S_OK == hr) foSize = LI_To_FO(stat.cbSize); else foSize = foNil; if (lperrb) *lperrb = hr; return foSize; } /////////////////////////////////////////////////////////////////// // These functions came from iofts.c /////////////////////////////////////////////////////////////////// PUBLIC HFPB FAR PASCAL FileCreate (HFPB hfpbSysFile, LPCSTR lszFilename, int fFileType, LPERRB lperrb) { LPFPB lpfpb; /* Pointer to file parameter block */ HANDLE hMem; HFPB hfpb; HRESULT hr; OLECHAR wszFileName[_MAX_PATH]; FM fm; HFS hfs; /* Check for valid filename */ if (lszFilename == NULL ) { SetErrCode (lperrb, E_INVALIDARG); return 0; } /* Allocate a file's parameter block */ if (!(hMem = _GLOBALALLOC(GMEM_ZEROINIT, sizeof(FPB)))) { SetErrCode(lperrb, E_OUTOFMEMORY); return NULL; } if (!(lpfpb = (LPFPB)_GLOBALLOCK(hMem))) { _GLOBALUNLOCK(hMem); SetErrCode(lperrb,E_OUTOFMEMORY); return NULL; } _INITIALIZECRITICALSECTION(&lpfpb->cs); lpfpb->hStruct = hMem; switch (fFileType) { case FS_SYSTEMFILE: IClassFactory* pCF; hr = CoGetClassObject(CLSID_ITStorage, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (VOID **)&pCF); // Error check! IITStorage* pITStorage; hr = pCF->CreateInstance(NULL, IID_ITStorage, (VOID **)&pITStorage); if (pCF) pCF->Release(); fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fm, -1, wszFileName, _MAX_PATH); hr = pITStorage->StgCreateDocfile(wszFileName, STGM_READWRITE, RESERVED, &hfs); // if call failed, make sure to set hfs NULL if (!SUCCEEDED(hr)) { hfs = NULL; SetErrCode(lperrb, hr); } lpfpb->fs.hfs = hfs; if (pITStorage) pITStorage->Release(); DisposeFm(fm); break; case FS_SUBFILE: hfs = GetHfs(hfpbSysFile,lszFilename,TRUE,lperrb); if (hfs) { lpfpb->fs.hf = HfCreateFileHfs(hfs,GetSubFilename(lszFilename, NULL),HFOPEN_READWRITE,lperrb); lpfpb->ioMode = OF_READWRITE; if (lpfpb->fs.hf == NULL) { if (!hfpbSysFile) RcCloseHfs(hfs); goto ErrorExit; } else { if (!hfpbSysFile) lpfpb->ioMode |= OPENED_HFS; } } else { goto ErrorExit; } break; case REGULAR_FILE: // Create the file if ((lpfpb->fs.hFile = (HFILE_GENERIC)CREAT (lszFilename, 0)) == HFILE_GENERIC_ERROR) { SetErrCode(lperrb,E_FILECREATE); goto ErrorExit; } lpfpb->ioMode = OF_READWRITE; break; } // Set the filetype lpfpb->fFileType = (BYTE) fFileType; _GLOBALUNLOCK(hfpb = lpfpb->hStruct); return hfpb; ErrorExit: _DELETECRITICALSECTION(&lpfpb->cs); _GLOBALFREE(hMem); return 0; } PUBLIC HFPB FAR PASCAL FileOpen (HFPB hfpbSysFile, LPCSTR lszFilename, int fFileType, int ioMode, LPERRB lperrb) { LPFPB lpfpb; /* Pointer to file parameter block */ HANDLE hMem; HFPB hfpb; FM fm; OLECHAR wszFileName[_MAX_PATH]; HFS hfs; HRESULT hr; /* Check for valid filename */ if (lszFilename == NULL ) { SetErrCode (lperrb, E_INVALIDARG); return 0; } /* Allocate a file's parameter block */ if (!(hMem = _GLOBALALLOC(GMEM_ZEROINIT, sizeof(FPB)))) { SetErrCode(lperrb,E_OUTOFMEMORY); return NULL; } if (!(lpfpb = (LPFPB)_GLOBALLOCK(hMem))) { _GLOBALUNLOCK(hMem); SetErrCode(lperrb,E_OUTOFMEMORY); return NULL; } _INITIALIZECRITICALSECTION(&lpfpb->cs); lpfpb->hStruct = hMem; switch (fFileType) { case FS_SYSTEMFILE: IClassFactory* pCF; hr = CoGetClassObject(CLSID_ITStorage, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (VOID **)&pCF); // Error check! IITStorage* pITStorage; hr = pCF->CreateInstance(NULL, IID_ITStorage, (VOID **)&pITStorage); if (pCF) pCF->Release(); fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fm, -1, wszFileName, _MAX_PATH); hr = pITStorage->StgOpenStorage(wszFileName, NULL, (ioMode==READ) ? STGM_READ:STGM_READWRITE, NULL, RESERVED, &hfs); if (!SUCCEEDED(hr)) { hfs = NULL; SetErrCode(lperrb, hr); } lpfpb->fs.hfs = hfs; if (pITStorage) pITStorage->Release(); DisposeFm(fm); break; case FS_SUBFILE: hfs = GetHfs(hfpbSysFile,lszFilename,FALSE,lperrb); if (hfs) { OLECHAR wsz[_MAX_PATH]; LPCSTR sz = GetSubFilename(lszFilename, NULL); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sz, -1, wsz, _MAX_PATH); lpfpb->fs.hf = HfOpenHfs(hfs, wsz, (BYTE)((ioMode==READ)?HFOPEN_READ:HFOPEN_READWRITE),lperrb); lpfpb->ioMode = (BYTE) ioMode; if (lpfpb->fs.hf == 0) { if (!hfpbSysFile) RcCloseHfs(hfs); SetErrCode (lperrb, E_NOTEXIST); goto ErrorExit; } else { if (!hfpbSysFile) lpfpb->ioMode|=OPENED_HFS; } } else { SetErrCode (lperrb, E_NOTEXIST); goto ErrorExit; } break; case REGULAR_FILE: /* Set the IO mode and appropriate error messages */ if (ioMode == READ) { /* Open the file */ if ((lpfpb->fs.hFile = (HFILE_GENERIC)OPEN (lszFilename, ioMode)) == HFILE_GENERIC_ERROR) { SetErrCode(lperrb,E_NOTEXIST); goto ErrorExit; } } else { ioMode = OF_READWRITE; /* Open the file */ if ((lpfpb->fs.hFile = (HFILE_GENERIC)OPEN(lszFilename, ioMode)) == HFILE_GENERIC_ERROR) { SetErrCode(lperrb,E_FILECREATE); goto ErrorExit; } } lpfpb->ioMode = (BYTE) ioMode; break; } // set filetype lpfpb->fFileType = (BYTE) fFileType; _GLOBALUNLOCK(hfpb = lpfpb->hStruct); return hfpb; ErrorExit: _DELETECRITICALSECTION(&lpfpb->cs); _GLOBALFREE(hMem); return 0; } PUBLIC RC FAR PASCAL FileClose(HFPB hfpb) { RC rc; LPFPB lpfpb; if (hfpb == NULL) return E_HANDLE; lpfpb = (LPFPB)_GLOBALLOCK(hfpb); _ENTERCRITICALSECTION(&lpfpb->cs); rc = S_OK; switch (lpfpb->fFileType) { case FS_SYSTEMFILE: if (lpfpb->fs.hfs) lpfpb->fs.hfs->Release(); break; case FS_SUBFILE: if (lpfpb->fs.hf) lpfpb->fs.hf->Release(); break; case REGULAR_FILE: if (lpfpb->fs.hFile) rc = (!CloseHandle(lpfpb->fs.hFile))?E_FILECLOSE:S_OK; break; } /* Free the file parameter block structure */ _LEAVECRITICALSECTION(&lpfpb->cs); _DELETECRITICALSECTION(&lpfpb->cs); _GLOBALUNLOCK(hfpb); _GLOBALFREE(hfpb); return rc; } // These are verbatim from iofts.c. I put them here so we can compile PRIVATE HANDLE NEAR PASCAL IoftsWin32Create(LPCSTR lpstr, DWORD w) { SECURITY_ATTRIBUTES sa; HANDLE hfile; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = 0; hfile= CreateFile(lpstr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); return hfile; } PRIVATE HANDLE NEAR PASCAL IoftsWin32Open(LPCSTR lpstr, DWORD w) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = 0; return CreateFile(lpstr, (w == READ) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } #if 0 // This is new functionality PUBLIC FM EXPORT_API FAR PASCAL FmFromHfs(HFS hfs) { char szStoreName[_MAX_PATH]; FM fm; ERRB errb; STATSTG StoreStat; HRESULT hr; // get storage name // Turns out this isn't IMPLEMENTED yet! hr = hfs->Stat(&StoreStat, STATFLAG_DEFAULT); if (S_OK == hr) { // and convert it since FMs aren't Unicode WideCharToMultiByte(CP_ACP, 0, StoreStat.pwcsName, -1, szStoreName, _MAX_PATH, NULL, NULL); // free memory associated with pwcsName CoTaskMemFree(StoreStat.pwcsName); // create new FM fm = FmNew(szStoreName, &errb); } else fm = NULL; return fm; } #endif