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