1 //---------------------------------------------------------------
2 //
3 //  For conditions of distribution and use, see copyright notice
4 //  in Flashpix.h
5 //
6 //  Copyright (c) 1999 Digital Imaging Group, Inc.
7 //
8 //  Contents: Reference ILockBytes class
9 //
10 //  Classes:  CFileILB
11 //
12 //  Notes:      This Class always call single byte I/O routines
13 //              because most systems only have support for single byte
14 //              I/O. This makes the code more portable.
15 //
16 //----------------------------------------------------------------------------
17 
18 
19 #include "msfhead.cxx"
20 #include <errno.h>
21 #include "h/refilb.hxx"
22 #include <stdio.h>
23 #ifdef __sun__
24 //  FIXME: realpath, mapped via _fullpath macro, is not ANSI C
25 //  This is here so we can still use g++'s -ansi
26   extern "C" { extern char *realpath(const char *, char *); }
27 #endif
28 #include <stdlib.h>
29 
30 #include <sys/stat.h>
31 #include "time.hxx"
32 #include "h/tchar.h"
33 
34 #ifdef _WIN32
35 #include <io.h> // to get definition of wunlink
36 #else
37 #include <unistd.h>
38 // get the correct stat structure
39 #endif
40 
41 #include <stdlib.h>
42 #include "h/ole.hxx"
43 
44 DECLARE_INFOLEVEL(ol, DEB_ERROR)
45 
46 static int filenum = 0;
47 
GetTempFileName(void)48 char * GetTempFileName(void)
49 {
50     char *psz = new char[_MAX_PATH +1];
51     strcpy(psz, "dft");
52 
53     _itoa(filenum, psz + 3, 10);
54     filenum++;
55     return psz;
56 }
57 
CFileILB(const TCHAR * pszName,DWORD grfMode,BOOL fOpenFile)58 CFileILB::CFileILB(const TCHAR *pszName,
59                    DWORD grfMode,
60                    BOOL fOpenFile/* =TRUE */)
61 {
62     _pszName = NULL;
63 
64     _fDelete = FALSE;
65     if (pszName == NULL)
66     {
67          _pszName = GetTempFileName();
68          _unlink(_pszName);            // make sure file is over written
69          _fDelete |= ILB_DELETEONERR;  // don't want to keep scratch files
70     }
71     else
72     {
73         _pszName = new char[_MAX_PATH + 1];
74         TTOS(pszName, _pszName, _tcslen(pszName)+1);
75     }
76 
77     if (grfMode & STGM_DELETEONRELEASE)
78         _fDelete |= ILB_DELETEONRELEASE;
79     _f = NULL;
80     if (fOpenFile)
81     {
82         // disregard if file is already there
83   Create(STGM_CREATE|STGM_READWRITE);
84         // got to open the file with this option
85         olAssert(_f && "CFileILB could not open the file!");
86     }
87     _ulRef = 1;
88 }
89 
90 static const char pcszReadOnly[] ="rb";
91 static const char pcszReadWrite[] = "r+b";
92 static const char pcszWrite[] = "w+b";
93 
Create(DWORD grfMode)94 SCODE CFileILB::Create(DWORD grfMode)
95 {
96     char const *pszMode = pcszReadOnly; // default
97 
98     if (grfMode & STGM_READWRITE)
99         pszMode = pcszReadWrite;
100     else {
101         olDebugOut((DEB_ITRACE, "CFileILB::Create called with Read Only!!\n"));
102     }
103 
104     _f = fopen(_pszName, pszMode);
105     if (_f)                     // open succeeded
106     {
107         if ((grfMode & (STGM_CREATE|STGM_CONVERT) ) == STGM_FAILIFTHERE)
108             return STG_E_FILEALREADYEXISTS;
109     }
110     else if (errno==EACCES && (grfMode & STGM_CONVERT))
111     {
112         olDebugOut((DEB_ERROR,"Access Denied in CFileILB::Create\n"));
113         return STG_E_ACCESSDENIED;
114     }
115     else
116     {
117         // the file does not exists, create the file
118         _f = fopen(_pszName, pcszWrite);
119         if (_f==NULL)
120         {
121             // we could not create the file for some reason
122             // return the appropriate error code
123             if (errno== EACCES)
124                 return STG_E_ACCESSDENIED;
125             else
126             {
127                 return STG_E_INVALIDNAME; // assume it is an invalid name
128             }
129         }
130         else
131         {
132             // the newly create file should be deleted on error
133             _fDelete |= ILB_DELETEONERR;
134         }
135     }
136     return S_OK;
137 }
138 
Open(DWORD grfMode)139 SCODE CFileILB::Open(DWORD grfMode)
140 {
141     char const *pszMode = pcszReadOnly; // default
142 
143     // this means an null named file
144     olAssert( (_fDelete & ILB_DELETEONERR)==0 );
145                                                   // has been opened
146     if (grfMode & STGM_READWRITE)
147         pszMode = pcszReadWrite;
148     else {
149         olDebugOut((DEB_ITRACE, "CFileILB::Open called with Read Only!!\n"));
150     }
151 
152     _f = fopen(_pszName, pszMode);
153     if (_f == NULL)
154     {
155         if (errno==EACCES) return STG_E_ACCESSDENIED;
156         else if (errno==ENOENT) return STG_E_FILENOTFOUND;
157         else return STG_E_INVALIDNAME; // we assume that the name is invalid
158     }
159 
160     return S_OK;
161 }
162 
~CFileILB()163 CFileILB::~CFileILB()
164 {
165     if (_f)
166         fclose(_f);
167     if (_fDelete & ILB_DELETEONRELEASE)
168     {
169          // nothing we can do if the file cannot be deleted somehow
170          // since the ref impl. is not multi-thread safe
171         _unlink(_pszName);
172     }
173     delete[] _pszName;
174 }
175 
QueryInterface(REFIID riid,LPVOID FAR * ppvObj)176 STDMETHODIMP CFileILB::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
177 {
178     *ppvObj = NULL;
179     UNREFERENCED_PARM(riid);
180     olAssert(FALSE && aMsg("function not implemented!"));
181     return ResultFromScode(STG_E_INVALIDFUNCTION);
182 }
183 
STDMETHODIMP_(ULONG)184 STDMETHODIMP_(ULONG) CFileILB::AddRef(void)
185 {
186     AtomicInc(&_ulRef);
187     return(_ulRef);
188 }
189 
STDMETHODIMP_(ULONG)190 STDMETHODIMP_(ULONG) CFileILB::Release(void)
191 {
192     AtomicDec(&_ulRef);
193     olDebugOut( (DEB_ITRACE, "CFileILB::Release => %lx\n", _ulRef) );
194     if (_ulRef > 0)
195         return(_ulRef);
196     delete this;
197 
198     return(0);
199 }
200 
ReleaseOnError(void)201 ULONG CFileILB::ReleaseOnError(void)
202 {
203     // this function should be not used otherwise
204     olAssert(_ulRef == 1);
205 
206     // Delete the file if it is a file we just created
207     if (_fDelete & ILB_DELETEONERR)
208         _fDelete |= ILB_DELETEONRELEASE;
209     return( Release() );
210 }
211 
ReadAt(ULARGE_INTEGER ulPosition,VOID HUGEP * pb,ULONG cb,ULONG * pcbRead)212 STDMETHODIMP CFileILB::ReadAt(ULARGE_INTEGER ulPosition,
213 
214         VOID HUGEP *pb,
215         ULONG cb,
216         ULONG *pcbRead)
217 {
218     fseek(_f, ULIGetLow(ulPosition), SEEK_SET);
219 
220     *pcbRead = fread(pb, 1, cb, _f);
221     return NOERROR;
222 }
223 
WriteAt(ULARGE_INTEGER ulPosition,VOID const HUGEP * pb,ULONG cb,ULONG FAR * pcbWritten)224 STDMETHODIMP CFileILB::WriteAt(ULARGE_INTEGER ulPosition,
225         VOID const HUGEP *pb,
226         ULONG cb,
227         ULONG FAR *pcbWritten)
228 {
229     fseek(_f, ULIGetLow(ulPosition), SEEK_SET);
230 
231     *pcbWritten = fwrite(pb, 1, cb, _f);
232     return NOERROR;
233 }
234 
Flush(void)235 STDMETHODIMP CFileILB::Flush(void)
236 {
237     fflush(_f);
238     return NOERROR;
239 }
240 
SetSize(ULARGE_INTEGER cb)241 STDMETHODIMP CFileILB::SetSize(ULARGE_INTEGER cb)
242 {
243     fseek(_f, ULIGetLow(cb), SEEK_SET);
244 
245     fwrite("", 0, 0, _f);
246     return NOERROR;
247 }
248 
LockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)249 STDMETHODIMP CFileILB::LockRegion(ULARGE_INTEGER libOffset,
250                                   ULARGE_INTEGER cb,
251                                   DWORD dwLockType)
252 {
253     UNREFERENCED_PARM(dwLockType);
254     UNREFERENCED_PARM(cb);
255     UNREFERENCED_PARM(libOffset);
256     olAssert(FALSE && aMsg("function not implemented!"));
257     return ResultFromScode(STG_E_INVALIDFUNCTION);
258 }
259 
260 
UnlockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)261 STDMETHODIMP CFileILB::UnlockRegion(ULARGE_INTEGER libOffset,
262         ULARGE_INTEGER cb,
263         DWORD dwLockType)
264 {
265     UNREFERENCED_PARM(dwLockType);
266     UNREFERENCED_PARM(cb);
267     UNREFERENCED_PARM(libOffset);
268     olAssert(FALSE && aMsg("function not implemented!"));
269     return ResultFromScode(STG_E_INVALIDFUNCTION);
270 }
271 
272 
Stat(STATSTG FAR * pstatstg,DWORD grfStatFlag)273 STDMETHODIMP CFileILB::Stat(STATSTG FAR *pstatstg, DWORD grfStatFlag)
274 {
275     memset(pstatstg, 0, sizeof(STATSTG));
276 
277     if ((grfStatFlag & STATFLAG_NONAME) == 0)
278     {
279          char pchTemp[_MAX_PATH+1];
280         _fullpath(pchTemp, _pszName, _MAX_PATH+1);
281         pstatstg->pwcsName = new TCHAR[strlen(pchTemp)+1];
282         STOT(pchTemp, pstatstg->pwcsName, strlen(pchTemp)+1);
283     }
284 
285     pstatstg->type = STGTY_LOCKBYTES;
286 
287     ULISetHigh(pstatstg->cbSize, 0);
288 
289     fseek(_f, 0, SEEK_END);
290     ULISetLow(pstatstg->cbSize, ftell(_f));
291 
292     // just return a default, the function that calls this should fill in
293     // the structure.
294     pstatstg->grfMode = STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE;
295 
296     struct _stat buf;
297     int result = _stat(_pszName, &buf);
298     if (!result)  // fill in zeros
299     {
300         pstatstg->atime.dwLowDateTime = 0;
301         pstatstg->mtime.dwLowDateTime = 0;
302         pstatstg->ctime.dwLowDateTime = 0;
303     }
304     else
305     {
306         TimeTToFileTime(&buf.st_atime, &pstatstg->atime);
307         TimeTToFileTime(&buf.st_mtime, &pstatstg->mtime);
308         TimeTToFileTime(&buf.st_ctime, &pstatstg->ctime);
309     }
310     return NOERROR;
311 }
312 
STDAPI_(BOOL)313 EXTERN_C STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
314 {
315     return (memcmp(&rguid1, &rguid2, sizeof(GUID)) == 0);
316 }
317