ReactOS  0.4.14-dev-57-g333b8f1
cabinet_main.c
Go to the documentation of this file.
1 /*
2  * cabinet.dll main
3  *
4  * Copyright 2002 Patrik Stridvall
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <string.h>
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #define NO_SHLWAPI_REG
31 #include "shlwapi.h"
32 #undef NO_SHLWAPI_REG
33 
34 #include "cabinet.h"
35 
36 #include "wine/debug.h"
37 
39 
40 
41 /***********************************************************************
42  * DllGetVersion (CABINET.2)
43  *
44  * Retrieves version information of the 'CABINET.DLL'
45  *
46  * PARAMS
47  * pdvi [O] pointer to version information structure.
48  *
49  * RETURNS
50  * Success: S_OK
51  * Failure: E_INVALIDARG
52  *
53  * NOTES
54  * Supposedly returns version from IE6SP1RP1
55  */
57 {
58  WARN("hmmm... not right version number \"5.1.1106.1\"?\n");
59 
60  if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) return E_INVALIDARG;
61 
62  pdvi->dwMajorVersion = 5;
63  pdvi->dwMinorVersion = 1;
64  pdvi->dwBuildNumber = 1106;
65  pdvi->dwPlatformID = 1;
66 
67  return S_OK;
68 }
69 
70 /* FDI callback functions */
71 
72 static void * CDECL mem_alloc(ULONG cb)
73 {
74  return HeapAlloc(GetProcessHeap(), 0, cb);
75 }
76 
77 static void CDECL mem_free(void *memory)
78 {
80 }
81 
82 static INT_PTR CDECL fdi_open(char *pszFile, int oflag, int pmode)
83 {
84  HANDLE handle;
85  DWORD dwAccess = 0;
86  DWORD dwShareMode = 0;
87  DWORD dwCreateDisposition;
88 
89  switch (oflag & _O_ACCMODE)
90  {
91  case _O_RDONLY:
92  dwAccess = GENERIC_READ;
93  dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
94  break;
95  case _O_WRONLY:
96  dwAccess = GENERIC_WRITE;
98  break;
99  case _O_RDWR:
100  dwAccess = GENERIC_READ | GENERIC_WRITE;
102  break;
103  }
104 
105  if (oflag & _O_CREAT)
106  {
107  dwCreateDisposition = OPEN_ALWAYS;
108  if (oflag & _O_EXCL) dwCreateDisposition = CREATE_NEW;
109  else if (oflag & _O_TRUNC) dwCreateDisposition = CREATE_ALWAYS;
110  }
111  else
112  {
113  dwCreateDisposition = OPEN_EXISTING;
114  if (oflag & _O_TRUNC) dwCreateDisposition = TRUNCATE_EXISTING;
115  }
116 
117  handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
118  dwCreateDisposition, 0, NULL);
119 
120  return (INT_PTR) handle;
121 }
122 
123 static UINT CDECL fdi_read(INT_PTR hf, void *pv, UINT cb)
124 {
125  HANDLE handle = (HANDLE) hf;
126  DWORD dwRead;
127 
128  if (ReadFile(handle, pv, cb, &dwRead, NULL))
129  return dwRead;
130 
131  return 0;
132 }
133 
134 static UINT CDECL fdi_write(INT_PTR hf, void *pv, UINT cb)
135 {
136  HANDLE handle = (HANDLE) hf;
137  DWORD dwWritten;
138 
139  if (WriteFile(handle, pv, cb, &dwWritten, NULL))
140  return dwWritten;
141 
142  return 0;
143 }
144 
145 static int CDECL fdi_close(INT_PTR hf)
146 {
147  HANDLE handle = (HANDLE) hf;
148  return CloseHandle(handle) ? 0 : -1;
149 }
150 
151 static LONG CDECL fdi_seek(INT_PTR hf, LONG dist, int seektype)
152 {
153  HANDLE handle = (HANDLE) hf;
154  return SetFilePointer(handle, dist, NULL, seektype);
155 }
156 
157 static void fill_file_node(struct FILELIST *pNode, LPCSTR szFilename)
158 {
159  pNode->next = NULL;
160  pNode->DoExtract = FALSE;
161 
162  pNode->FileName = HeapAlloc(GetProcessHeap(), 0, strlen(szFilename) + 1);
163  lstrcpyA(pNode->FileName, szFilename);
164 }
165 
166 static BOOL file_in_list(struct FILELIST *pNode, LPCSTR szFilename,
167  struct FILELIST **pOut)
168 {
169  while (pNode)
170  {
171  if (!lstrcmpiA(pNode->FileName, szFilename))
172  {
173  if (pOut)
174  *pOut = pNode;
175 
176  return TRUE;
177  }
178 
179  pNode = pNode->next;
180  }
181 
182  return FALSE;
183 }
184 
186 {
187  switch (fdint)
188  {
189  case fdintCOPY_FILE:
190  {
191  struct FILELIST *fileList, *node = NULL;
192  SESSION *pDestination = pfdin->pv;
193  LPSTR szFullPath, szDirectory;
194  HANDLE hFile = 0;
195  DWORD dwSize;
196 
197  dwSize = lstrlenA(pDestination->Destination) +
198  lstrlenA("\\") + lstrlenA(pfdin->psz1) + 1;
199  szFullPath = HeapAlloc(GetProcessHeap(), 0, dwSize);
200 
201  lstrcpyA(szFullPath, pDestination->Destination);
202  lstrcatA(szFullPath, "\\");
203  lstrcatA(szFullPath, pfdin->psz1);
204 
205  /* pull out the destination directory string from the full path */
206  dwSize = strrchr(szFullPath, '\\') - szFullPath + 1;
207  szDirectory = HeapAlloc(GetProcessHeap(), 0, dwSize);
208  lstrcpynA(szDirectory, szFullPath, dwSize);
209 
210  pDestination->FileSize += pfdin->cb;
211 
212  if (pDestination->Operation & EXTRACT_FILLFILELIST)
213  {
214  fileList = HeapAlloc(GetProcessHeap(), 0,
215  sizeof(struct FILELIST));
216 
217  fill_file_node(fileList, pfdin->psz1);
218  fileList->DoExtract = TRUE;
219  fileList->next = pDestination->FileList;
220  pDestination->FileList = fileList;
221  lstrcpyA(pDestination->CurrentFile, szFullPath);
222  pDestination->FileCount++;
223  }
224 
225  if ((pDestination->Operation & EXTRACT_EXTRACTFILES) ||
226  file_in_list(pDestination->FilterList, pfdin->psz1, NULL))
227  {
228  /* find the file node */
229  file_in_list(pDestination->FileList, pfdin->psz1, &node);
230 
231  if (node && !node->DoExtract)
232  {
233  HeapFree(GetProcessHeap(), 0, szFullPath);
234  HeapFree(GetProcessHeap(), 0, szDirectory);
235  return 0;
236  }
237 
238  /* create the destination directory if it doesn't exist */
239  if (GetFileAttributesA(szDirectory) == INVALID_FILE_ATTRIBUTES)
240  {
241  char *ptr;
242 
243  for(ptr = szDirectory + strlen(pDestination->Destination)+1; *ptr; ptr++) {
244  if(*ptr == '\\') {
245  *ptr = 0;
246  CreateDirectoryA(szDirectory, NULL);
247  *ptr = '\\';
248  }
249  }
250  CreateDirectoryA(szDirectory, NULL);
251  }
252 
253  hFile = CreateFileA(szFullPath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
255 
256  if (hFile != INVALID_HANDLE_VALUE && node)
257  node->DoExtract = FALSE;
258  }
259 
260  HeapFree(GetProcessHeap(), 0, szFullPath);
261  HeapFree(GetProcessHeap(), 0, szDirectory);
262 
263  return (INT_PTR) hFile;
264  }
265 
267  {
268  FILETIME ft;
269  FILETIME ftLocal;
270  HANDLE handle = (HANDLE) pfdin->hf;
271 
272  if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
273  return FALSE;
274 
275  if (!LocalFileTimeToFileTime(&ft, &ftLocal))
276  return FALSE;
277 
278  if (!SetFileTime(handle, &ftLocal, 0, &ftLocal))
279  return FALSE;
280 
282  return TRUE;
283  }
284 
285  default:
286  return 0;
287  }
288 }
289 
290 /***********************************************************************
291  * Extract (CABINET.3)
292  *
293  * Extracts the contents of the cabinet file to the specified
294  * destination.
295  *
296  * PARAMS
297  * dest [I/O] Controls the operation of Extract. See NOTES.
298  * szCabName [I] Filename of the cabinet to extract.
299  *
300  * RETURNS
301  * Success: S_OK.
302  * Failure: E_FAIL.
303  *
304  * NOTES
305  * The following members of the dest struct control the operation
306  * of Extract:
307  * FileSize [O] The size of all files extracted up to CurrentFile.
308  * Error [O] The error in case the extract operation fails.
309  * FileList [I] A linked list of filenames. Extract only extracts
310  * files from the cabinet that are in this list.
311  * FileCount [O] Contains the number of files in FileList on
312  * completion.
313  * Operation [I] See Operation.
314  * Destination [I] The destination directory.
315  * CurrentFile [O] The last file extracted.
316  * FilterList [I] A linked list of files that should not be extracted.
317  *
318  * Operation
319  * If Operation contains EXTRACT_FILLFILELIST, then FileList will be
320  * filled with all the files in the cabinet. If Operation contains
321  * EXTRACT_EXTRACTFILES, then only the files in the FileList will
322  * be extracted from the cabinet. EXTRACT_FILLFILELIST can be called
323  * by itself, but EXTRACT_EXTRACTFILES must have a valid FileList
324  * in order to succeed. If Operation contains both EXTRACT_FILLFILELIST
325  * and EXTRACT_EXTRACTFILES, then all the files in the cabinet
326  * will be extracted.
327  */
329 {
330  HRESULT res = S_OK;
331  HFDI hfdi;
332  char *str, *end, *path = NULL, *name = NULL;
333 
334  TRACE("(%p, %s)\n", dest, debugstr_a(szCabName));
335 
336  hfdi = FDICreate(mem_alloc,
337  mem_free,
338  fdi_open,
339  fdi_read,
340  fdi_write,
341  fdi_close,
342  fdi_seek,
343  cpuUNKNOWN,
344  &dest->Error);
345 
346  if (!hfdi)
347  return E_FAIL;
348 
349  if (GetFileAttributesA(dest->Destination) == INVALID_FILE_ATTRIBUTES)
350  {
351  res = S_OK;
352  goto end;
353  }
354 
355  /* split the cabinet name into path + name */
356  str = HeapAlloc(GetProcessHeap(), 0, lstrlenA(szCabName)+1);
357  if (!str)
358  {
359  res = E_OUTOFMEMORY;
360  goto end;
361  }
362  lstrcpyA(str, szCabName);
363 
364  if ((end = strrchr(str, '\\')))
365  {
366  path = str;
367  end++;
368  name = HeapAlloc( GetProcessHeap(), 0, strlen(end) + 1 );
369  if (!name)
370  {
371  res = E_OUTOFMEMORY;
372  goto end;
373  }
374  strcpy( name, end );
375  *end = 0;
376  }
377  else
378  {
379  name = str;
380  path = NULL;
381  }
382 
383  dest->FileSize = 0;
384 
385  if (!FDICopy(hfdi, name, path, 0,
388 
389 end:
392  FDIDestroy(hfdi);
393  return res;
394 }
INT FileCount
Definition: files.c:533
LONG cb
Definition: fdi.h:227
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
BOOL __cdecl FDIDestroy(HFDI hfdi)
Definition: fdi.c:2831
DWORD dwMinorVersion
Definition: shlwapi.h:1956
struct FILELIST * FilterList
Definition: files.c:538
static int CDECL fdi_close(INT_PTR hf)
Definition: cabinet_main.c:145
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define _O_RDONLY
Definition: cabinet.h:37
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
static LONG CDECL fdi_seek(INT_PTR hf, LONG dist, int seektype)
Definition: cabinet_main.c:151
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
WINE_DEFAULT_DEBUG_CHANNEL(cabinet)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define EXTRACT_EXTRACTFILES
Definition: files.c:521
static void *CDECL mem_alloc(ULONG cb)
Definition: cabinet_main.c:72
struct FILELIST * FileList
Definition: files.c:532
#define _O_CREAT
Definition: cabinet.h:46
#define WARN(fmt,...)
Definition: debug.h:111
static UINT CDECL fdi_read(INT_PTR hf, void *pv, UINT cb)
Definition: cabinet_main.c:123
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
HRESULT WINAPI Extract(SESSION *dest, LPCSTR szCabName)
Definition: cabinet_main.c:328
USHORT time
Definition: fdi.h:236
GLuint GLuint end
Definition: gl.h:1545
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
int32_t INT_PTR
Definition: typedefs.h:62
char * LPSTR
Definition: xmlstorage.h:182
#define E_FAIL
Definition: ddrawi.h:102
static char memory[1024 *256]
Definition: process.c:116
#define FILE_SHARE_READ
Definition: compat.h:125
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:1098
HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
Definition: cabinet_main.c:56
BOOL WINAPI LocalFileTimeToFileTime(IN CONST FILETIME *lpLocalFileTime, OUT LPFILETIME lpFileTime)
Definition: time.c:243
#define _O_RDWR
Definition: cabinet.h:39
static void CDECL mem_free(void *memory)
Definition: cabinet_main.c:77
#define _O_EXCL
Definition: cabinet.h:48
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define cpuUNKNOWN
Definition: fdi.h:269
DWORD dwBuildNumber
Definition: shlwapi.h:1957
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
FDINOTIFICATIONTYPE
Definition: fdi.h:246
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
BOOL __cdecl FDICopy(HFDI hfdi, char *pszCabinet, char *pszCabPath, int flags, PFNFDINOTIFY pfnfdin, PFNFDIDECRYPT pfnfdid, void *pvUser)
Definition: fdi.c:2431
#define GENERIC_WRITE
Definition: nt_native.h:90
static PVOID ptr
Definition: dispmode.c:27
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
CHAR CurrentFile[MAX_PATH]
Definition: files.c:536
DWORD dwMajorVersion
Definition: shlwapi.h:1955
smooth NULL
Definition: ftsmooth.c:416
static BOOL file_in_list(struct FILELIST *pNode, LPCSTR szFilename, struct FILELIST **pOut)
Definition: cabinet_main.c:166
char * psz1
Definition: fdi.h:228
HFDI __cdecl FDICreate(PFNALLOC pfnalloc, PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, PERF perf)
Definition: fdi.c:412
#define _O_TRUNC
Definition: cabinet.h:47
const char * LPCSTR
Definition: xmlstorage.h:183
#define EXTRACT_FILLFILELIST
Definition: files.c:520
#define OPEN_EXISTING
Definition: compat.h:426
BOOL DoExtract
Definition: files.c:526
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
if(!(yy_init))
Definition: macro.lex.yy.c:714
BOOL WINAPI DosDateTimeToFileTime(IN WORD wFatDate, IN WORD wFatTime, OUT LPFILETIME lpFileTime)
Definition: time.c:75
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:77
#define WINAPI
Definition: msvc.h:8
Definition: files.c:529
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
#define OPEN_ALWAYS
Definition: disk.h:70
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
INT FileSize
Definition: files.c:530
static DWORD cb
Definition: integrity.c:41
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
struct FILELIST * next
Definition: files.c:525
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
USHORT date
Definition: fdi.h:235
INT_PTR hf
Definition: fdi.h:233
#define GENERIC_READ
Definition: compat.h:124
DWORD dwPlatformID
Definition: shlwapi.h:1958
#define _O_ACCMODE
Definition: cabinet.h:40
_In_ HANDLE hFile
Definition: mswsock.h:90
INT Operation
Definition: files.c:534
#define _O_WRONLY
Definition: cabinet.h:38
LPSTR FileName
Definition: files.c:524
#define S_OK
Definition: intsafe.h:59
#define CREATE_ALWAYS
Definition: disk.h:72
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
static void fill_file_node(struct FILELIST *pNode, LPCSTR szFilename)
Definition: cabinet_main.c:157
#define CDECL
Definition: compat.h:21
Definition: services.c:325
unsigned int UINT
Definition: ndis.h:50
void * pv
Definition: fdi.h:231
#define lstrcpynA
Definition: compat.h:408
Definition: name.c:36
GLuint res
Definition: glext.h:9613
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
static UINT CDECL fdi_write(INT_PTR hf, void *pv, UINT cb)
Definition: cabinet_main.c:134
static char * dest
Definition: rtl.c:135
#define CREATE_NEW
Definition: disk.h:69
#define TRUNCATE_EXISTING
Definition: disk.h:71
static INT_PTR CDECL fdi_notify_extract(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: cabinet_main.c:185
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:399
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
CHAR Destination[MAX_PATH]
Definition: files.c:535
#define HeapFree(x, y, z)
Definition: compat.h:394
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
static INT_PTR CDECL fdi_open(char *pszFile, int oflag, int pmode)
Definition: cabinet_main.c:82
Definition: dlist.c:348