/***************************************************************************\ * * FSMISC.C * * Copyright (C) Microsoft Corporation 1990. * All Rights reserved. * ***************************************************************************** * * Program Description: File System Manager functions - miscellaneous * ***************************************************************************** * * Revision History: Created 03/12/90 by JohnSc * ***************************************************************************** * * Known Bugs: None * \***************************************************************************/ #include "help.h" #include "inc\fspriv.h" #pragma hdrstop // This is hacked in for 3.1 bug #1013. #include <sys/types.h> /***************************************************************************\ * * Function: FAccessHfs( hfs, sz, bFlags ) * * Purpose: Determine existence or legal access to a FS file * * ASSUMES * * args IN: hfs * sz - file name * bFlags - ignored * * PROMISES * * returns: TRUE if file exists (is accessible in stated mode), * FALSE otherwise * * Bugs: access mode part is unimplemented * \***************************************************************************/ BOOL STDCALL FAccessHfs(HFS hfs, LPSTR sz) { QFSHR qfshr; FILE_REC fr; ASSERT(hfs != NULL); qfshr = PtrFromGh(hfs); if (qfshr->fid == HFILE_ERROR && !FPlungeQfshr(qfshr)) return FALSE; SetFSErrorRc(RcLookupByKey(qfshr->hbt, (KEY) sz, NULL, &fr)); return (rcFSError == rcSuccess); } /***************************************************************************\ * - Function: RcLLInfoFromHf( hf, wOption, qfid, qlBase, qlcb ) - * Purpose: Map an HF into low level file info. * * ASSUMES * args IN: hf - an open HF * qfid, qlBase, qlcb - pointers to user's variables * wOption - wLLSameFid, wLLDupFid, or wLLNewFid * * PROMISES * returns: RcFSError(); rcSuccess on success * * args OUT: qfid - depending on value of wOption, either * the same fid used by hf, a dup() of this fid, * or a new fid obtained by reopening the file. * * qlBase - byte offset of first byte in the file * qlcb - size in bytes of the data in the file * * globals OUT: rcFSError * * Notes: It is possible to read data outside the range specified * by *qlBase and *qlcb. Nothing is guaranteed about what * will be found there. * If wOption is wLLSameFid or wLLDupFid, and the FS is * opened in write mode, this fid will be writable. * However, writing is not allowed and may destroy the * file system. * * Fids obtained with the options wLLSameFid and wLLDupFid * share a file pointer with the hfs. This file pointer * may change after any operation on this FS. * The fid obtained with the option wLLSameFid may be closed * by FS operations. If it is, your fid is invalid. * * NULL can be passed for qfid, qlbase, qlcb and this routine * will not pass back the information. * * Bugs: wLLDupFid is unimplemented. * * +++ * * Method: * * Notes: * \***************************************************************************/ RC STDCALL RcLLInfoFromHf(HF hf, WORD wOption, FID *qfid, QL qlBase, QL qlcb) { QRWFO qrwfo = (QRWFO) PtrFromGh(hf); QFSHR qfshr = (QFSHR) PtrFromGh(qrwfo->hfs); if (!(qrwfo->bFlags & fFSOpenReadOnly)) { SetFSErrorRc(rcNoPermission); return rcFSError; } if (qfshr->fid == HFILE_ERROR && !FPlungeQfshr(qfshr)) return rcFSError; if (qlBase != NULL) *qlBase = qrwfo->lifBase + sizeof(FH); if (qlcb != NULL) *qlcb = qrwfo->lcbFile; if (qfid != NULL) { switch (wOption) { case LLSAMEFID: *qfid = qfshr->fid; break; case LLDUPFID: SetFSErrorRc(rcUnimplemented); // REVIEW break; case LLNEWFID: *qfid = FidOpenFm(qfshr->fm, OF_READ); if (*qfid == HFILE_ERROR) SetFSErrorRc(RcGetIOError()); break; default: SetFSErrorRc( rcBadArg ); break; } } return rcFSError; } /***************************************************************************\ * - Function: RcLLInfoFromHfsSz( hfs, sz, wOption, qfid, qlBase, qlcb ) - * Purpose: Map an HF into low level file info. * * ASSUMES * args IN: hfs - an open HFS * szName - name of file in FS * qfid, qlBase, qlcb - pointers to user's variables * wOption - wLLSameFid, wLLDupFid, or wLLNewFid * * PROMISES * returns: RcFSError(); rcSuccess on success * * args OUT: qfid - depending on value of wOption, either * the same fid used by hf, a dup() of this fid, * or a new fid obtained by reopening the file. * * qlBase - byte offset of first byte in the file * qlcb - size in bytes of the data in the file * * globals OUT: rcFSError * * Notes: It is possible to read data outside the range specified * by *qlBase and *qlcb. Nothing is guaranteed about what * will be found there. * If wOption is wLLSameFid or wLLDupFid, and the FS is * opened in write mode, this fid will be writable. * However, writing is not allowed and may destroy the * file system. * * Fids obtained with the options wLLSameFid and wLLDupFid * share a file pointer with the hfs. This file pointer * may change after any operation on this FS. * The fid obtained with the option wLLSameFid may be closed * by FS operations. If it is, your fid is invalid. * * NULL can be passed for qfid, qlbase, qlcb and this routine * will not pass back the information. * * Bugs: wLLDupFid is unimplemented. * * +++ * * Method: Calls RcLLInfoFromHf(). * * Notes: * \***************************************************************************/ RC STDCALL RcLLInfoFromHfsSz( HFS hfs, LPSTR szFile, WORD wOption, FID *qfid, QL qlBase, QL qlcb ) { HF hf = HfOpenHfs(hfs, szFile, fFSOpenReadOnly); RC rc; if (!hf) return rcFSError; rc = RcLLInfoFromHf(hf, wOption, qfid, qlBase, qlcb); return (rcSuccess == RcCloseHf(hf)) ? rcFSError : rc; } /***************************************************************************\ * - Function: RcTimestampHfs( hfs, ql ) - * Purpose: Get the modification time of the FS. * * ASSUMES * args IN: hfs - FS * ql - pointer to a long * * PROMISES * returns: rcSuccess or what ever * args OUT: ql - contains time of last modification of the * file. This will not necessarily reflect * writes to open files within the FS. * * NOTE: This code is WINDOWS specific. The platform * independent code is in Winhelp 3.5. * \***************************************************************************/ RC STDCALL RcTimestampHfs(HFS hfs, DWORD* plTime) { QFSHR qfshr; BY_HANDLE_FILE_INFORMATION bhfi; ASSERT(hfs != NULL); ASSERT(plTime != NULL); qfshr = (QFSHR) PtrFromGh(hfs); if (qfshr->fid != HFILE_ERROR || FPlungeQfshr(qfshr)) { if (!GetFileInformationByHandle((HANDLE) qfshr->fid, &bhfi)) { WIN32_FIND_DATA fd; HANDLE hfd; if ((hfd = FindFirstFile(qfshr->fm, &fd)) != INVALID_HANDLE_VALUE) { *plTime = fd.ftLastWriteTime.dwLowDateTime; FindClose(hfd); AdjustForTimeZoneBias(plTime); return rcSuccess; } return rcBadHandle; } else { *plTime = bhfi.ftLastWriteTime.dwLowDateTime; AdjustForTimeZoneBias(plTime); return rcSuccess; } } return rcBadHandle; } /*************************************************************************** FUNCTION: MatchTimestamp PURPOSE: Determine if a file has the expected time/date stamp. If the file isn't where it is expected, try to find it elsewhere. PARAMETERS: pszFile lTime pfm -- NULL to prevent looking elsewhere for a file RETURNS: TRUE if the dates match, FALSE if file isn't found or dates don't match. If the file is in a different location, the time/date stamp matches, then pfm will be non-null COMMENTS: MODIFICATION DATES: 18-Sep-1994 [ralphw] ***************************************************************************/ BOOL STDCALL MatchTimestamp(PCSTR pszFile, DWORD lTime, FM* pfm) { WIN32_FIND_DATA fd; HANDLE hfind = FindFirstFile(pszFile, &fd); if (hfind == INVALID_HANDLE_VALUE) { if (!pfm) return FALSE; *pfm = FmNewExistSzDir(pszFile, DIR_INI | DIR_PATH | DIR_CUR_HELP | DIR_CURRENT | DIR_SILENT_REG); if (!*pfm) return FALSE; hfind = FindFirstFile(*pfm, &fd); if (hfind == INVALID_HANDLE_VALUE) return FALSE; } else if (pfm) *pfm = NULL; // path is valid FindClose(hfind); AdjustForTimeZoneBias(&fd.ftLastWriteTime.dwLowDateTime); #ifdef _DEBUG if ((lTime != fd.ftLastWriteTime.dwLowDateTime)) { char szBuf[521]; wsprintf(szBuf, "Timestamp doesn't match: %s\r\n", pszFile); SendStringToParent(szBuf); } #endif return (lTime == fd.ftLastWriteTime.dwLowDateTime); } /*************************************************************************** FUNCTION: AdjustForTimeZoneBias PURPOSE: Adjusts the given timestamp from local time to UTC using the time zone bias from GetTimeZoneInformation. PARAMETERS: lpTimestamp RETURNS: none. COMMENTS: All timestamps are assumed to be from FILETIME.dwLowDateTime. MODIFICATION DATES: 18-Sep-1994 [ralphw] ***************************************************************************/ // # of 100nSec intervals in 1 minute #define T100NSECPERMINUTE (60 * 1000 * 10000) void STDCALL AdjustForTimeZoneBias(LPDWORD lpTimestamp) { TIME_ZONE_INFORMATION tzi; LONG Bias; switch (GetTimeZoneInformation(&tzi)) { case TIME_ZONE_ID_DAYLIGHT: Bias = tzi.Bias + tzi.DaylightBias; break; case TIME_ZONE_ID_STANDARD: Bias = tzi.Bias + tzi.StandardBias; break; case TIME_ZONE_ID_UNKNOWN: Bias = tzi.Bias; break; default: Bias = 0; break; } *lpTimestamp -= Bias * T100NSECPERMINUTE; } #ifndef _X86_ /***************************************************************************\ * - Function: iSdffFileIdHfs( hfs ) - * Purpose: Obtain the SDFF file id associated with a file. * * ASSUMES * args IN: hfs - valid handle to a file system. * * PROMISES * returns: The sdff file id. All FS files have such an ID, so this * function cannot fail. * * Note: someday this may be a macro. * \***************************************************************************/ #if defined(MAC) && defined(QUIT_TUNE) #pragma segment quit #endif int PASCAL ISdffFileIdHfs( HFS hfs ) { QFSHR qfshr; int iFile; ASSERT( hfs != (HFS)-1 ); qfshr = PtrFromGh( hfs ); iFile = qfshr->fsh.sdff_file_id; //UnlockGh( hfs ); return( iFile ); } #if defined(MAC) && defined(QUIT_TUNE) #pragma segment fsmisc #endif /* Same thing, but takes an HF rather than HFS: */ #if defined(MAC) && defined(QUIT_TUNE) #pragma segment quit #endif int PASCAL ISdffFileIdHf( HF hf ) { QRWFO qrwfo; int iFile; ASSERT( hf != (HFS)-1 ); qrwfo = PtrFromGh( hf ); iFile = ISdffFileIdHfs( qrwfo->hfs ); //UnlockGh( hf ); return( iFile ); } #if defined(MAC) && defined(QUIT_TUNE) #pragma segment fsmisc #endif #endif //!_X86_ /* EOF */