Synchronize with trunk's revision r57652.
[reactos.git] / dll / win32 / setupapi / setupcab.c
1 /*
2 * Setupapi cabinet routines
3 *
4 * Copyright 2003 Gregory M. Turner
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 * Many useful traces are commented in code, uncomment them if you have
22 * trouble and run with WINEDEBUG=+setupapi
23 *
24 */
25
26 #include "setupapi_private.h"
27
28 HINSTANCE hInstance = 0;
29 OSVERSIONINFOW OsVersionInfo;
30
31 static HINSTANCE CABINET_hInstance = 0;
32
33 static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN,
34 PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF);
35
36 static BOOL (__cdecl *sc_FDICopy)(HFDI, char *, char *, int,
37 PFNFDINOTIFY, PFNFDIDECRYPT, void *);
38
39 static BOOL (__cdecl *sc_FDIDestroy)(HFDI);
40
41 #define SC_HSC_A_MAGIC 0xACABFEED
42 typedef struct {
43 UINT magic;
44 HFDI hfdi;
45 PSP_FILE_CALLBACK_A msghandler;
46 PVOID context;
47 CHAR most_recent_cabinet_name[MAX_PATH];
48 } SC_HSC_A, *PSC_HSC_A;
49
50 #define SC_HSC_W_MAGIC 0x0CABFEED
51 typedef struct {
52 UINT magic;
53 HFDI hfdi;
54 PSP_FILE_CALLBACK_W msghandler;
55 PVOID context;
56 WCHAR most_recent_cabinet_name[MAX_PATH];
57 } SC_HSC_W, *PSC_HSC_W;
58
59 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
60
61 static BOOL LoadCABINETDll(void)
62 {
63 if (!CABINET_hInstance) {
64 CABINET_hInstance = LoadLibraryA("cabinet.dll");
65 if (CABINET_hInstance) {
66 sc_FDICreate = (void *)GetProcAddress(CABINET_hInstance, "FDICreate");
67 sc_FDICopy = (void *)GetProcAddress(CABINET_hInstance, "FDICopy");
68 sc_FDIDestroy = (void *)GetProcAddress(CABINET_hInstance, "FDIDestroy");
69 return TRUE;
70 } else {
71 ERR("load cabinet dll failed.\n");
72 return FALSE;
73 }
74 } else
75 return TRUE;
76 }
77
78 static void UnloadCABINETDll(void)
79 {
80 if (CABINET_hInstance) {
81 FreeLibrary(CABINET_hInstance);
82 CABINET_hInstance = 0;
83 }
84 }
85
86 /* FDICreate callbacks */
87
88 static void *sc_cb_alloc(ULONG cb)
89 {
90 return HeapAlloc(GetProcessHeap(), 0, cb);
91 }
92
93 static void sc_cb_free(void *pv)
94 {
95 HeapFree(GetProcessHeap(), 0, pv);
96 }
97
98 static INT_PTR sc_cb_open(char *pszFile, int oflag, int pmode)
99 {
100 DWORD creation = 0, sharing = 0;
101 int ioflag = 0;
102 INT_PTR ret = 0;
103 SECURITY_ATTRIBUTES sa;
104
105 /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */
106
107 switch(oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
108 case _O_RDONLY:
109 ioflag |= GENERIC_READ;
110 break;
111 case _O_WRONLY:
112 ioflag |= GENERIC_WRITE;
113 break;
114 case _O_RDWR:
115 ioflag |= GENERIC_READ & GENERIC_WRITE;
116 break;
117 case _O_WRONLY | _O_RDWR: /* hmmm.. */
118 ERR("_O_WRONLY & _O_RDWR in oflag?\n");
119 return -1;
120 }
121
122 if (oflag & _O_CREAT) {
123 if (oflag & _O_EXCL)
124 creation = CREATE_NEW;
125 else if (oflag & _O_TRUNC)
126 creation = CREATE_ALWAYS;
127 else
128 creation = OPEN_ALWAYS;
129 } else /* no _O_CREAT */ {
130 if (oflag & _O_TRUNC)
131 creation = TRUNCATE_EXISTING;
132 else
133 creation = OPEN_EXISTING;
134 }
135
136 switch( pmode & 0x70 ) {
137 case _SH_DENYRW:
138 sharing = 0L;
139 break;
140 case _SH_DENYWR:
141 sharing = FILE_SHARE_READ;
142 break;
143 case _SH_DENYRD:
144 sharing = FILE_SHARE_WRITE;
145 break;
146 case _SH_COMPAT:
147 case _SH_DENYNO:
148 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
149 break;
150 default:
151 ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode);
152 return -1;
153 }
154
155 if (oflag & ~(_O_BINARY | _O_TRUNC | _O_EXCL | _O_CREAT | _O_RDWR | _O_WRONLY | _O_NOINHERIT))
156 WARN("unsupported oflag 0x%04x\n",oflag);
157
158 sa.nLength = sizeof( SECURITY_ATTRIBUTES );
159 sa.lpSecurityDescriptor = NULL;
160 sa.bInheritHandle = (ioflag & _O_NOINHERIT) ? FALSE : TRUE;
161
162 ret = (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL);
163
164 /* TRACE("<-- %d\n", ret); */
165
166 return ret;
167 }
168
169 static UINT sc_cb_read(INT_PTR hf, void *pv, UINT cb)
170 {
171 DWORD num_read;
172 BOOL rslt;
173
174 /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
175
176 rslt = ReadFile((HANDLE) hf, pv, cb, &num_read, NULL);
177
178
179 /* eof and failure both give "-1" return */
180 if ((! rslt) || ((cb > 0) && (num_read == 0))) {
181 /* TRACE("<-- -1\n"); */
182 return -1;
183 }
184
185 /* TRACE("<-- %lu\n", num_read); */
186 return num_read;
187 }
188
189 static UINT sc_cb_write(INT_PTR hf, void *pv, UINT cb)
190 {
191 DWORD num_written;
192 /* BOOL rv; */
193
194 /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
195
196 if ( /* (rv = */ WriteFile((HANDLE) hf, pv, cb, &num_written, NULL) /* ) */
197 && (num_written == cb)) {
198 /* TRACE("<-- %lu\n", num_written); */
199 return num_written;
200 } else {
201 /* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */
202 /* TRACE("<-- -1\n"); */
203 return -1;
204 }
205 }
206
207 static int sc_cb_close(INT_PTR hf)
208 {
209 /* TRACE("(hf == %d)\n", hf); */
210
211 if (CloseHandle((HANDLE) hf))
212 return 0;
213 else
214 return -1;
215 }
216
217 static long sc_cb_lseek(INT_PTR hf, long dist, int seektype)
218 {
219 DWORD ret;
220
221 /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
222
223 if (seektype < 0 || seektype > 2)
224 return -1;
225
226 if (((ret = SetFilePointer((HANDLE) hf, dist, NULL, seektype)) != INVALID_SET_FILE_POINTER) || !GetLastError()) {
227 /* TRACE("<-- %lu\n", ret); */
228 return ret;
229 } else {
230 /* TRACE("<-- -1\n"); */
231 return -1;
232 }
233 }
234
235 #define SIZEOF_MYSTERIO (MAX_PATH*3)
236
237 /* FDICopy callbacks */
238
239 static INT_PTR sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
240 {
241 FILE_IN_CABINET_INFO_A fici;
242 PSC_HSC_A phsc;
243 CABINET_INFO_A ci;
244 FILEPATHS_A fp;
245 UINT err;
246
247 CHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! probably 256... */
248
249 memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO);
250
251 TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
252
253 if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_A_MAGIC))
254 phsc = (PSC_HSC_A) pfdin->pv;
255 else {
256 ERR("pv %p is not an SC_HSC_A.\n", (pfdin) ? pfdin->pv : NULL);
257 return -1;
258 }
259
260 switch (fdint) {
261 case fdintCABINET_INFO:
262 TRACE("Cabinet info notification\n");
263 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
264 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
265 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
266 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
267 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
268 WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
269 ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
270 ci.CabinetPath = pfdin->psz3;
271 ci.DiskName = pfdin->psz2;
272 ci.SetId = pfdin->setID;
273 ci.CabinetNumber = pfdin->iCabinet;
274 phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0);
275 return 0;
276 case fdintPARTIAL_FILE:
277 TRACE("Partial file notification\n");
278 /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
279 return 0;
280 case fdintCOPY_FILE:
281 TRACE("Copy file notification\n");
282 TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
283 /* TRACE(" File size: %ld\n", pfdin->cb);
284 TRACE(" File date: %u\n", pfdin->date);
285 TRACE(" File time: %u\n", pfdin->time);
286 TRACE(" File attr: %u\n", pfdin->attribs); */
287 fici.NameInCabinet = pfdin->psz1;
288 fici.FileSize = pfdin->cb;
289 fici.Win32Error = 0;
290 fici.DosDate = pfdin->date;
291 fici.DosTime = pfdin->time;
292 fici.DosAttribs = pfdin->attribs;
293 memset(&(fici.FullTargetName[0]), 0, MAX_PATH);
294 err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
295 (UINT) &fici, (UINT) pfdin->psz1);
296 if (err == FILEOP_DOIT) {
297 TRACE(" Callback specified filename: %s\n", debugstr_a(&(fici.FullTargetName[0])));
298 if (!fici.FullTargetName[0]) {
299 WARN(" Empty return string causing abort.\n");
300 SetLastError(ERROR_PATH_NOT_FOUND);
301 return -1;
302 }
303 return sc_cb_open(&(fici.FullTargetName[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
304 } else {
305 TRACE(" Callback skipped file.\n");
306 return 0;
307 }
308 case fdintCLOSE_FILE_INFO:
309 TRACE("Close file notification\n");
310 /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
311 TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
312 TRACE(" File hndl: %d\n", pfdin->hf); */
313 fp.Source = &(phsc->most_recent_cabinet_name[0]);
314 fp.Target = pfdin->psz1;
315 fp.Win32Error = 0;
316 fp.Flags = 0;
317 /* the following should be a fixme -- but it occurs too many times */
318 WARN("Should set file date/time/attribs (and execute files?)\n");
319 err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
320 if (sc_cb_close(pfdin->hf))
321 WARN("_close failed.\n");
322 if (err) {
323 SetLastError(err);
324 return FALSE;
325 } else
326 return TRUE;
327 case fdintNEXT_CABINET:
328 TRACE("Next cabinet notification\n");
329 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
330 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
331 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
332 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
333 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
334 ci.CabinetFile = pfdin->psz1;
335 ci.CabinetPath = pfdin->psz3;
336 ci.DiskName = pfdin->psz2;
337 ci.SetId = pfdin->setID;
338 ci.CabinetNumber = pfdin->iCabinet;
339 /* remember the new cabinet name */
340 strcpy(&(phsc->most_recent_cabinet_name[0]), pfdin->psz1);
341 err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0]));
342 if (err) {
343 SetLastError(err);
344 return -1;
345 } else {
346 if (mysterio[0]) {
347 /* some easy paranoia. no such carefulness exists on the wide API IIRC */
348 lstrcpynA(pfdin->psz3, &(mysterio[0]), SIZEOF_MYSTERIO);
349 }
350 return 0;
351 }
352 default:
353 FIXME("Unknown notification type %d.\n", fdint);
354 return 0;
355 }
356 }
357
358 static INT_PTR sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
359 {
360 FILE_IN_CABINET_INFO_W fici;
361 PSC_HSC_W phsc;
362 CABINET_INFO_W ci;
363 FILEPATHS_W fp;
364 UINT err;
365 int len;
366
367 WCHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! */
368 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
369 CHAR charbuf[MAX_PATH];
370
371 memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO * sizeof(WCHAR));
372 memset(&(buf[0]), 0, MAX_PATH * sizeof(WCHAR));
373 memset(&(buf2[0]), 0, MAX_PATH * sizeof(WCHAR));
374 memset(&(charbuf[0]), 0, MAX_PATH);
375
376 TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
377
378 if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_W_MAGIC))
379 phsc = (PSC_HSC_W) pfdin->pv;
380 else {
381 ERR("pv %p is not an SC_HSC_W.\n", (pfdin) ? pfdin->pv : NULL);
382 return -1;
383 }
384
385 switch (fdint) {
386 case fdintCABINET_INFO:
387 TRACE("Cabinet info notification\n");
388 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
389 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
390 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
391 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
392 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
393 WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
394 ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
395 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH);
396 if ((len > MAX_PATH) || (len <= 1))
397 buf[0] = '\0';
398 ci.CabinetPath = &(buf[0]);
399 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH);
400 if ((len > MAX_PATH) || (len <= 1))
401 buf2[0] = '\0';
402 ci.DiskName = &(buf2[0]);
403 ci.SetId = pfdin->setID;
404 ci.CabinetNumber = pfdin->iCabinet;
405 phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0);
406 return 0;
407 case fdintPARTIAL_FILE:
408 TRACE("Partial file notification\n");
409 /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
410 return 0;
411 case fdintCOPY_FILE:
412 TRACE("Copy file notification\n");
413 TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
414 /* TRACE(" File size: %ld\n", pfdin->cb);
415 TRACE(" File date: %u\n", pfdin->date);
416 TRACE(" File time: %u\n", pfdin->time);
417 TRACE(" File attr: %u\n", pfdin->attribs); */
418 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf2[0]), MAX_PATH);
419 if ((len > MAX_PATH) || (len <= 1))
420 buf2[0] = '\0';
421 fici.NameInCabinet = &(buf2[0]);
422 fici.FileSize = pfdin->cb;
423 fici.Win32Error = 0;
424 fici.DosDate = pfdin->date;
425 fici.DosTime = pfdin->time;
426 fici.DosAttribs = pfdin->attribs;
427 memset(&(fici.FullTargetName[0]), 0, MAX_PATH * sizeof(WCHAR));
428 err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
429 (UINT) &fici, (UINT) pfdin->psz1);
430 if (err == FILEOP_DOIT) {
431 TRACE(" Callback specified filename: %s\n", debugstr_w(&(fici.FullTargetName[0])));
432 if (fici.FullTargetName[0]) {
433 len = strlenW(&(fici.FullTargetName[0])) + 1;
434 if ((len > MAX_PATH ) || (len <= 1))
435 return 0;
436 if (!WideCharToMultiByte(CP_ACP, 0, &(fici.FullTargetName[0]), len, &(charbuf[0]), MAX_PATH, 0, 0))
437 return 0;
438 } else {
439 WARN("Empty buffer string caused abort.\n");
440 SetLastError(ERROR_PATH_NOT_FOUND);
441 return -1;
442 }
443 return sc_cb_open(&(charbuf[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
444 } else {
445 TRACE(" Callback skipped file.\n");
446 return 0;
447 }
448 case fdintCLOSE_FILE_INFO:
449 TRACE("Close file notification\n");
450 /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
451 TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
452 TRACE(" File hndl: %d\n", pfdin->hf); */
453 fp.Source = &(phsc->most_recent_cabinet_name[0]);
454 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf[0]), MAX_PATH);
455 if ((len > MAX_PATH) || (len <= 1))
456 buf[0] = '\0';
457 fp.Target = &(buf[0]);
458 fp.Win32Error = 0;
459 fp.Flags = 0;
460 /* a valid fixme -- but occurs too many times */
461 /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */
462 err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
463 if (sc_cb_close(pfdin->hf))
464 WARN("_close failed.\n");
465 if (err) {
466 SetLastError(err);
467 return FALSE;
468 } else
469 return TRUE;
470 case fdintNEXT_CABINET:
471 TRACE("Next cabinet notification\n");
472 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
473 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
474 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
475 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
476 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
477 /* remember the new cabinet name */
478 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(phsc->most_recent_cabinet_name[0]), MAX_PATH);
479 if ((len > MAX_PATH) || (len <= 1))
480 phsc->most_recent_cabinet_name[0] = '\0';
481 ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
482 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH);
483 if ((len > MAX_PATH) || (len <= 1))
484 buf[0] = '\0';
485 ci.CabinetPath = &(buf[0]);
486 len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH);
487 if ((len > MAX_PATH) || (len <= 1))
488 buf2[0] = '\0';
489 ci.DiskName = &(buf2[0]);
490 ci.SetId = pfdin->setID;
491 ci.CabinetNumber = pfdin->iCabinet;
492 err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0]));
493 if (err) {
494 SetLastError(err);
495 return -1;
496 } else {
497 if (mysterio[0]) {
498 len = strlenW(&(mysterio[0])) + 1;
499 if ((len > 255) || (len <= 1))
500 return 0;
501 if (!WideCharToMultiByte(CP_ACP, 0, &(mysterio[0]), len, pfdin->psz3, 255, 0, 0))
502 return 0;
503 }
504 return 0;
505 }
506 default:
507 FIXME("Unknown notification type %d.\n", fdint);
508 return 0;
509 }
510 }
511
512 /***********************************************************************
513 * SetupIterateCabinetA (SETUPAPI.@)
514 */
515 BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
516 PSP_FILE_CALLBACK_A MsgHandler, PVOID Context)
517 {
518
519 SC_HSC_A my_hsc;
520 ERF erf;
521 CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p = NULL;
522 DWORD fpnsize;
523 BOOL ret;
524
525
526 TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
527 debugstr_a(CabinetFile), Reserved, MsgHandler, Context);
528
529 if (! LoadCABINETDll())
530 return FALSE;
531
532 if (!CabinetFile)
533 {
534 SetLastError(ERROR_INVALID_PARAMETER);
535 return FALSE;
536 }
537
538 memset(&my_hsc, 0, sizeof(SC_HSC_A));
539 pszCabinet[0] = '\0';
540 pszCabPath[0] = '\0';
541
542 fpnsize = strlen(CabinetFile);
543 if (fpnsize >= MAX_PATH) {
544 SetLastError(ERROR_BAD_PATHNAME);
545 return FALSE;
546 }
547
548 fpnsize = GetFullPathNameA(CabinetFile, MAX_PATH, &(pszCabPath[0]), &p);
549 if (fpnsize > MAX_PATH) {
550 SetLastError(ERROR_BAD_PATHNAME);
551 return FALSE;
552 }
553
554 if (p) {
555 strcpy(pszCabinet, p);
556 *p = '\0';
557 } else {
558 strcpy(pszCabinet, CabinetFile);
559 pszCabPath[0] = '\0';
560 }
561
562 TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
563
564 /* remember the cabinet name */
565 strcpy(&(my_hsc.most_recent_cabinet_name[0]), pszCabinet);
566
567 my_hsc.magic = SC_HSC_A_MAGIC;
568 my_hsc.msghandler = MsgHandler;
569 my_hsc.context = Context;
570 my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read,
571 sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf );
572
573 if (!my_hsc.hfdi) return FALSE;
574
575 ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath,
576 0, sc_FNNOTIFY_A, NULL, &my_hsc) ) ? TRUE : FALSE;
577
578 sc_FDIDestroy(my_hsc.hfdi);
579 return ret;
580 }
581
582
583 /***********************************************************************
584 * SetupIterateCabinetW (SETUPAPI.@)
585 */
586 BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved,
587 PSP_FILE_CALLBACK_W MsgHandler, PVOID Context)
588 {
589 CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH];
590 UINT len;
591 SC_HSC_W my_hsc;
592 ERF erf;
593 WCHAR pszCabPathW[MAX_PATH], *p = NULL;
594 DWORD fpnsize;
595 BOOL ret;
596
597 TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
598 debugstr_w(CabinetFile), Reserved, MsgHandler, Context);
599
600 if (!LoadCABINETDll())
601 return FALSE;
602
603 if (!CabinetFile)
604 {
605 SetLastError(ERROR_INVALID_PARAMETER);
606 return FALSE;
607 }
608
609 memset(&my_hsc, 0, sizeof(SC_HSC_W));
610
611 fpnsize = GetFullPathNameW(CabinetFile, MAX_PATH, pszCabPathW, &p);
612 if (fpnsize > MAX_PATH) {
613 SetLastError(ERROR_BAD_PATHNAME);
614 return FALSE;
615 }
616
617 if (p) {
618 strcpyW(my_hsc.most_recent_cabinet_name, p);
619 *p = 0;
620 len = WideCharToMultiByte(CP_ACP, 0, pszCabPathW, -1, pszCabPath,
621 MAX_PATH, 0, 0);
622 if (!len) return FALSE;
623 } else {
624 strcpyW(my_hsc.most_recent_cabinet_name, CabinetFile);
625 pszCabPath[0] = '\0';
626 }
627
628 len = WideCharToMultiByte(CP_ACP, 0, my_hsc.most_recent_cabinet_name, -1,
629 pszCabinet, MAX_PATH, 0, 0);
630 if (!len) return FALSE;
631
632 TRACE("path: %s, cabfile: %s\n",
633 debugstr_a(pszCabPath), debugstr_a(pszCabinet));
634
635 my_hsc.magic = SC_HSC_W_MAGIC;
636 my_hsc.msghandler = MsgHandler;
637 my_hsc.context = Context;
638 my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read,
639 sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf );
640
641 if (!my_hsc.hfdi) return FALSE;
642
643 ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath,
644 0, sc_FNNOTIFY_W, NULL, &my_hsc) ) ? TRUE : FALSE;
645
646 sc_FDIDestroy(my_hsc.hfdi);
647 return ret;
648 }
649
650
651 /***********************************************************************
652 * DllMain
653 *
654 * PARAMS
655 * hinstDLL [I] handle to the DLL's instance
656 * fdwReason [I]
657 * lpvReserved [I] reserved, must be NULL
658 *
659 * RETURNS
660 * Success: TRUE
661 * Failure: FALSE
662 */
663
664 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
665 {
666 switch (fdwReason) {
667 case DLL_PROCESS_ATTACH:
668 DisableThreadLibraryCalls(hinstDLL);
669 OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
670 if (!GetVersionExW(&OsVersionInfo))
671 return FALSE;
672 hInstance = (HINSTANCE)hinstDLL;
673 break;
674 case DLL_PROCESS_DETACH:
675 UnloadCABINETDll();
676 break;
677 }
678
679 return TRUE;
680 }