2 * Setupapi cabinet routines
4 * Copyright 2003 Gregory M. Turner
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.
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.
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
21 * Many useful traces are commented in code, uncomment them if you have
22 * trouble and run with WINEDEBUG=+setupapi
26 #include "setupapi_private.h"
28 HINSTANCE hInstance
= 0;
29 OSVERSIONINFOW OsVersionInfo
;
31 static HINSTANCE CABINET_hInstance
= 0;
33 static HFDI (__cdecl
*sc_FDICreate
)(PFNALLOC
, PFNFREE
, PFNOPEN
,
34 PFNREAD
, PFNWRITE
, PFNCLOSE
, PFNSEEK
, int, PERF
);
36 static BOOL (__cdecl
*sc_FDICopy
)(HFDI
, char *, char *, int,
37 PFNFDINOTIFY
, PFNFDIDECRYPT
, void *);
39 static BOOL (__cdecl
*sc_FDIDestroy
)(HFDI
);
41 #define SC_HSC_A_MAGIC 0xACABFEED
45 PSP_FILE_CALLBACK_A msghandler
;
47 CHAR most_recent_cabinet_name
[MAX_PATH
];
48 } SC_HSC_A
, *PSC_HSC_A
;
50 #define SC_HSC_W_MAGIC 0x0CABFEED
54 PSP_FILE_CALLBACK_W msghandler
;
56 WCHAR most_recent_cabinet_name
[MAX_PATH
];
57 } SC_HSC_W
, *PSC_HSC_W
;
59 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
61 static BOOL
LoadCABINETDll(void)
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");
71 ERR("load cabinet dll failed.\n");
78 static void UnloadCABINETDll(void)
80 if (CABINET_hInstance
) {
81 FreeLibrary(CABINET_hInstance
);
82 CABINET_hInstance
= 0;
86 /* FDICreate callbacks */
88 static void *sc_cb_alloc(ULONG cb
)
90 return HeapAlloc(GetProcessHeap(), 0, cb
);
93 static void sc_cb_free(void *pv
)
95 HeapFree(GetProcessHeap(), 0, pv
);
98 static INT_PTR
sc_cb_open(char *pszFile
, int oflag
, int pmode
)
100 DWORD creation
= 0, sharing
= 0;
103 SECURITY_ATTRIBUTES sa
;
105 /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */
107 switch(oflag
& (_O_RDONLY
| _O_WRONLY
| _O_RDWR
)) {
109 ioflag
|= GENERIC_READ
;
112 ioflag
|= GENERIC_WRITE
;
115 ioflag
|= GENERIC_READ
& GENERIC_WRITE
;
117 case _O_WRONLY
| _O_RDWR
: /* hmmm.. */
118 ERR("_O_WRONLY & _O_RDWR in oflag?\n");
122 if (oflag
& _O_CREAT
) {
124 creation
= CREATE_NEW
;
125 else if (oflag
& _O_TRUNC
)
126 creation
= CREATE_ALWAYS
;
128 creation
= OPEN_ALWAYS
;
129 } else /* no _O_CREAT */ {
130 if (oflag
& _O_TRUNC
)
131 creation
= TRUNCATE_EXISTING
;
133 creation
= OPEN_EXISTING
;
136 switch( pmode
& 0x70 ) {
141 sharing
= FILE_SHARE_READ
;
144 sharing
= FILE_SHARE_WRITE
;
148 sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
151 ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode
);
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
);
158 sa
.nLength
= sizeof( SECURITY_ATTRIBUTES
);
159 sa
.lpSecurityDescriptor
= NULL
;
160 sa
.bInheritHandle
= (ioflag
& _O_NOINHERIT
) ? FALSE
: TRUE
;
162 ret
= (INT_PTR
) CreateFileA(pszFile
, ioflag
, sharing
, &sa
, creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
164 /* TRACE("<-- %d\n", ret); */
169 static UINT
sc_cb_read(INT_PTR hf
, void *pv
, UINT cb
)
174 /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
176 rslt
= ReadFile((HANDLE
) hf
, pv
, cb
, &num_read
, NULL
);
179 /* eof and failure both give "-1" return */
180 if ((! rslt
) || ((cb
> 0) && (num_read
== 0))) {
181 /* TRACE("<-- -1\n"); */
185 /* TRACE("<-- %lu\n", num_read); */
189 static UINT
sc_cb_write(INT_PTR hf
, void *pv
, UINT cb
)
194 /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
196 if ( /* (rv = */ WriteFile((HANDLE
) hf
, pv
, cb
, &num_written
, NULL
) /* ) */
197 && (num_written
== cb
)) {
198 /* TRACE("<-- %lu\n", num_written); */
201 /* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */
202 /* TRACE("<-- -1\n"); */
207 static int sc_cb_close(INT_PTR hf
)
209 /* TRACE("(hf == %d)\n", hf); */
211 if (CloseHandle((HANDLE
) hf
))
217 static long sc_cb_lseek(INT_PTR hf
, long dist
, int seektype
)
221 /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
223 if (seektype
< 0 || seektype
> 2)
226 if (((ret
= SetFilePointer((HANDLE
) hf
, dist
, NULL
, seektype
)) != INVALID_SET_FILE_POINTER
) || !GetLastError()) {
227 /* TRACE("<-- %lu\n", ret); */
230 /* TRACE("<-- -1\n"); */
235 #define SIZEOF_MYSTERIO (MAX_PATH*3)
237 /* FDICopy callbacks */
239 static INT_PTR
sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint
, PFDINOTIFICATION pfdin
)
241 FILE_IN_CABINET_INFO_A fici
;
247 CHAR mysterio
[SIZEOF_MYSTERIO
]; /* how big? undocumented! probably 256... */
249 memset(&(mysterio
[0]), 0, SIZEOF_MYSTERIO
);
251 TRACE("(fdint == %d, pfdin == ^%p)\n", fdint
, pfdin
);
253 if (pfdin
&& pfdin
->pv
&& (*((void **) pfdin
->pv
) == (void *)SC_HSC_A_MAGIC
))
254 phsc
= (PSC_HSC_A
) pfdin
->pv
;
256 ERR("pv %p is not an SC_HSC_A.\n", (pfdin
) ? pfdin
->pv
: NULL
);
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);
276 case fdintPARTIAL_FILE
:
277 TRACE("Partial file notification\n");
278 /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
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
;
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
);
303 return sc_cb_open(&(fici
.FullTargetName
[0]), _O_BINARY
| _O_CREAT
| _O_WRONLY
, _S_IREAD
| _S_IWRITE
);
305 TRACE(" Callback skipped file.\n");
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
;
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");
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]));
347 /* some easy paranoia. no such carefulness exists on the wide API IIRC */
348 lstrcpynA(pfdin
->psz3
, &(mysterio
[0]), SIZEOF_MYSTERIO
);
353 FIXME("Unknown notification type %d.\n", fdint
);
358 static INT_PTR
sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint
, PFDINOTIFICATION pfdin
)
360 FILE_IN_CABINET_INFO_W fici
;
367 WCHAR mysterio
[SIZEOF_MYSTERIO
]; /* how big? undocumented! */
368 WCHAR buf
[MAX_PATH
], buf2
[MAX_PATH
];
369 CHAR charbuf
[MAX_PATH
];
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
);
376 TRACE("(fdint == %d, pfdin == ^%p)\n", fdint
, pfdin
);
378 if (pfdin
&& pfdin
->pv
&& (*((void **) pfdin
->pv
) == (void *)SC_HSC_W_MAGIC
))
379 phsc
= (PSC_HSC_W
) pfdin
->pv
;
381 ERR("pv %p is not an SC_HSC_W.\n", (pfdin
) ? pfdin
->pv
: NULL
);
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))
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))
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);
407 case fdintPARTIAL_FILE
:
408 TRACE("Partial file notification\n");
409 /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
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))
421 fici
.NameInCabinet
= &(buf2
[0]);
422 fici
.FileSize
= pfdin
->cb
;
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))
436 if (!WideCharToMultiByte(CP_ACP
, 0, &(fici
.FullTargetName
[0]), len
, &(charbuf
[0]), MAX_PATH
, 0, 0))
439 WARN("Empty buffer string caused abort.\n");
440 SetLastError(ERROR_PATH_NOT_FOUND
);
443 return sc_cb_open(&(charbuf
[0]), _O_BINARY
| _O_CREAT
| _O_WRONLY
, _S_IREAD
| _S_IWRITE
);
445 TRACE(" Callback skipped file.\n");
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))
457 fp
.Target
= &(buf
[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");
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))
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))
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]));
498 len
= strlenW(&(mysterio
[0])) + 1;
499 if ((len
> 255) || (len
<= 1))
501 if (!WideCharToMultiByte(CP_ACP
, 0, &(mysterio
[0]), len
, pfdin
->psz3
, 255, 0, 0))
507 FIXME("Unknown notification type %d.\n", fdint
);
512 /***********************************************************************
513 * SetupIterateCabinetA (SETUPAPI.@)
515 BOOL WINAPI
SetupIterateCabinetA(PCSTR CabinetFile
, DWORD Reserved
,
516 PSP_FILE_CALLBACK_A MsgHandler
, PVOID Context
)
521 CHAR pszCabinet
[MAX_PATH
], pszCabPath
[MAX_PATH
], *p
= NULL
;
526 TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
527 debugstr_a(CabinetFile
), Reserved
, MsgHandler
, Context
);
529 if (! LoadCABINETDll())
534 SetLastError(ERROR_INVALID_PARAMETER
);
538 memset(&my_hsc
, 0, sizeof(SC_HSC_A
));
539 pszCabinet
[0] = '\0';
540 pszCabPath
[0] = '\0';
542 fpnsize
= strlen(CabinetFile
);
543 if (fpnsize
>= MAX_PATH
) {
544 SetLastError(ERROR_BAD_PATHNAME
);
548 fpnsize
= GetFullPathNameA(CabinetFile
, MAX_PATH
, &(pszCabPath
[0]), &p
);
549 if (fpnsize
> MAX_PATH
) {
550 SetLastError(ERROR_BAD_PATHNAME
);
555 strcpy(pszCabinet
, p
);
558 strcpy(pszCabinet
, CabinetFile
);
559 pszCabPath
[0] = '\0';
562 TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath
), debugstr_a(pszCabinet
));
564 /* remember the cabinet name */
565 strcpy(&(my_hsc
.most_recent_cabinet_name
[0]), pszCabinet
);
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
);
573 if (!my_hsc
.hfdi
) return FALSE
;
575 ret
= ( sc_FDICopy(my_hsc
.hfdi
, pszCabinet
, pszCabPath
,
576 0, sc_FNNOTIFY_A
, NULL
, &my_hsc
) ) ? TRUE
: FALSE
;
578 sc_FDIDestroy(my_hsc
.hfdi
);
583 /***********************************************************************
584 * SetupIterateCabinetW (SETUPAPI.@)
586 BOOL WINAPI
SetupIterateCabinetW(PCWSTR CabinetFile
, DWORD Reserved
,
587 PSP_FILE_CALLBACK_W MsgHandler
, PVOID Context
)
589 CHAR pszCabinet
[MAX_PATH
], pszCabPath
[MAX_PATH
];
593 WCHAR pszCabPathW
[MAX_PATH
], *p
= NULL
;
597 TRACE("(CabinetFile == %s, Reserved == %u, MsgHandler == ^%p, Context == ^%p)\n",
598 debugstr_w(CabinetFile
), Reserved
, MsgHandler
, Context
);
600 if (!LoadCABINETDll())
605 SetLastError(ERROR_INVALID_PARAMETER
);
609 memset(&my_hsc
, 0, sizeof(SC_HSC_W
));
611 fpnsize
= GetFullPathNameW(CabinetFile
, MAX_PATH
, pszCabPathW
, &p
);
612 if (fpnsize
> MAX_PATH
) {
613 SetLastError(ERROR_BAD_PATHNAME
);
618 strcpyW(my_hsc
.most_recent_cabinet_name
, p
);
620 len
= WideCharToMultiByte(CP_ACP
, 0, pszCabPathW
, -1, pszCabPath
,
622 if (!len
) return FALSE
;
624 strcpyW(my_hsc
.most_recent_cabinet_name
, CabinetFile
);
625 pszCabPath
[0] = '\0';
628 len
= WideCharToMultiByte(CP_ACP
, 0, my_hsc
.most_recent_cabinet_name
, -1,
629 pszCabinet
, MAX_PATH
, 0, 0);
630 if (!len
) return FALSE
;
632 TRACE("path: %s, cabfile: %s\n",
633 debugstr_a(pszCabPath
), debugstr_a(pszCabinet
));
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
);
641 if (!my_hsc
.hfdi
) return FALSE
;
643 ret
= ( sc_FDICopy(my_hsc
.hfdi
, pszCabinet
, pszCabPath
,
644 0, sc_FNNOTIFY_W
, NULL
, &my_hsc
) ) ? TRUE
: FALSE
;
646 sc_FDIDestroy(my_hsc
.hfdi
);
651 /***********************************************************************
655 * hinstDLL [I] handle to the DLL's instance
657 * lpvReserved [I] reserved, must be NULL
664 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
667 case DLL_PROCESS_ATTACH
:
668 DisableThreadLibraryCalls(hinstDLL
);
669 OsVersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOW
);
670 if (!GetVersionExW(&OsVersionInfo
))
672 hInstance
= (HINSTANCE
)hinstDLL
;
674 case DLL_PROCESS_DETACH
: