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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Many useful traces are commented in code, uncomment them if you have
22 * trouble and run with --debugmsg +setupapi
29 #include "setupapi_private.h"
31 #include "wine/unicode.h"
33 #include "msvcrt/fcntl.h"
34 #include "msvcrt/share.h"
36 #include "wine/debug.h"
38 static HINSTANCE CABINET_hInstance
= 0;
40 static HFDI (__cdecl
*sc_FDICreate
)(PFNALLOC
, PFNFREE
, PFNOPEN
,
41 PFNREAD
, PFNWRITE
, PFNCLOSE
, PFNSEEK
, int, PERF
);
43 static BOOL (__cdecl
*sc_FDICopy
)(HFDI
, char *, char *, int,
44 PFNFDINOTIFY
, PFNFDIDECRYPT
, void *);
46 static BOOL (__cdecl
*sc_FDIDestroy
)(HFDI
);
48 #define SC_HSC_A_MAGIC 0xACABFEED
52 PSP_FILE_CALLBACK_A msghandler
;
54 CHAR most_recent_cabinet_name
[MAX_PATH
];
55 } SC_HSC_A
, *PSC_HSC_A
;
57 #define SC_HSC_W_MAGIC 0x0CABFEED
61 PSP_FILE_CALLBACK_W msghandler
;
63 WCHAR most_recent_cabinet_name
[MAX_PATH
];
64 } SC_HSC_W
, *PSC_HSC_W
;
66 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
68 static BOOL
LoadCABINETDll(void)
70 if (!CABINET_hInstance
) {
71 CABINET_hInstance
= LoadLibraryA("cabinet.dll");
72 if (CABINET_hInstance
) {
73 sc_FDICreate
= (void *)GetProcAddress(CABINET_hInstance
, "FDICreate");
74 sc_FDICopy
= (void *)GetProcAddress(CABINET_hInstance
, "FDICopy");
75 sc_FDIDestroy
= (void *)GetProcAddress(CABINET_hInstance
, "FDIDestroy");
78 ERR("load cabinet dll failed.\n");
85 static void UnloadCABINETDll(void)
87 if (CABINET_hInstance
) {
88 FreeLibrary(CABINET_hInstance
);
89 CABINET_hInstance
= 0;
93 /* FDICreate callbacks */
95 static void *sc_cb_alloc(ULONG cb
)
100 static void sc_cb_free(void *pv
)
105 static INT_PTR
sc_cb_open(char *pszFile
, int oflag
, int pmode
)
107 DWORD creation
= 0, sharing
= 0;
110 SECURITY_ATTRIBUTES sa
;
112 /* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */
114 switch(oflag
& (_O_RDONLY
| _O_WRONLY
| _O_RDWR
)) {
116 ioflag
|= GENERIC_READ
;
119 ioflag
|= GENERIC_WRITE
;
122 ioflag
|= GENERIC_READ
& GENERIC_WRITE
;
124 case _O_WRONLY
| _O_RDWR
: /* hmmm.. */
125 ERR("_O_WRONLY & _O_RDWR in oflag?\n");
129 if (oflag
& _O_CREAT
) {
131 creation
= CREATE_NEW
;
132 else if (oflag
& _O_TRUNC
)
133 creation
= CREATE_ALWAYS
;
135 creation
= OPEN_ALWAYS
;
136 } else /* no _O_CREAT */ {
137 if (oflag
& _O_TRUNC
)
138 creation
= TRUNCATE_EXISTING
;
140 creation
= OPEN_EXISTING
;
143 switch( pmode
& 0x70 ) {
148 sharing
= FILE_SHARE_READ
;
151 sharing
= FILE_SHARE_WRITE
;
155 sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
158 ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode
);
162 if (oflag
& ~(_O_BINARY
| _O_TRUNC
| _O_EXCL
| _O_CREAT
| _O_RDWR
| _O_WRONLY
| _O_NOINHERIT
))
163 WARN("unsupported oflag 0x%04x\n",oflag
);
165 sa
.nLength
= sizeof( SECURITY_ATTRIBUTES
);
166 sa
.lpSecurityDescriptor
= NULL
;
167 sa
.bInheritHandle
= (ioflag
& _O_NOINHERIT
) ? FALSE
: TRUE
;
169 ret
= (INT_PTR
) CreateFileA(pszFile
, ioflag
, sharing
, &sa
, creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
171 /* TRACE("<-- %d\n", ret); */
176 static UINT
sc_cb_read(INT_PTR hf
, void *pv
, UINT cb
)
181 /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
183 rslt
= ReadFile((HANDLE
) hf
, pv
, cb
, &num_read
, NULL
);
186 /* eof and failure both give "-1" return */
187 if ((! rslt
) || ((cb
> 0) && (num_read
== 0))) {
188 /* TRACE("<-- -1\n"); */
192 /* TRACE("<-- %lu\n", num_read); */
196 static UINT
sc_cb_write(INT_PTR hf
, void *pv
, UINT cb
)
201 /* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
203 if ( /* (rv = */ WriteFile((HANDLE
) hf
, pv
, cb
, &num_written
, NULL
) /* ) */
204 && (num_written
== cb
)) {
205 /* TRACE("<-- %lu\n", num_written); */
208 /* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */
209 /* TRACE("<-- -1\n"); */
214 static int sc_cb_close(INT_PTR hf
)
216 /* TRACE("(hf == %d)\n", hf); */
218 if (CloseHandle((HANDLE
) hf
))
224 static long sc_cb_lseek(INT_PTR hf
, long dist
, int seektype
)
228 /* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
230 if (seektype
< 0 || seektype
> 2)
233 if (((ret
= SetFilePointer((HANDLE
) hf
, dist
, NULL
, seektype
)) != INVALID_SET_FILE_POINTER
) || !GetLastError()) {
234 /* TRACE("<-- %lu\n", ret); */
237 /* TRACE("<-- -1\n"); */
242 #define SIZEOF_MYSTERIO (MAX_PATH*3)
244 /* FDICopy callbacks */
246 static INT_PTR
sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint
, PFDINOTIFICATION pfdin
)
248 FILE_IN_CABINET_INFOA fici
;
254 CHAR mysterio
[SIZEOF_MYSTERIO
]; /* how big? undocumented! probably 256... */
256 memset(&(mysterio
[0]), 0, SIZEOF_MYSTERIO
);
258 TRACE("(fdint == %d, pfdin == ^%p)\n", fdint
, pfdin
);
260 if (pfdin
&& pfdin
->pv
&& (*((void **) pfdin
->pv
) == (void *)SC_HSC_A_MAGIC
))
261 phsc
= (PSC_HSC_A
) pfdin
->pv
;
263 ERR("pv %p is not an SC_HSC_A.\n", (pfdin
) ? pfdin
->pv
: NULL
);
268 case fdintCABINET_INFO
:
269 TRACE("Cabinet info notification\n");
270 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
271 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
272 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
273 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
274 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
275 WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
276 ci
.CabinetFile
= &(phsc
->most_recent_cabinet_name
[0]);
277 ci
.CabinetPath
= pfdin
->psz3
;
278 ci
.DiskName
= pfdin
->psz2
;
279 ci
.SetId
= pfdin
->setID
;
280 ci
.CabinetNumber
= pfdin
->iCabinet
;
281 phsc
->msghandler(phsc
->context
, SPFILENOTIFY_CABINETINFO
, (UINT
) &ci
, 0);
283 case fdintPARTIAL_FILE
:
284 TRACE("Partial file notification\n");
285 /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
288 TRACE("Copy file notification\n");
289 TRACE(" File name: %s\n", debugstr_a(pfdin
->psz1
));
290 /* TRACE(" File size: %ld\n", pfdin->cb);
291 TRACE(" File date: %u\n", pfdin->date);
292 TRACE(" File time: %u\n", pfdin->time);
293 TRACE(" File attr: %u\n", pfdin->attribs); */
294 fici
.NameInCabinet
= pfdin
->psz1
;
295 fici
.FileSize
= pfdin
->cb
;
297 fici
.DosDate
= pfdin
->date
;
298 fici
.DosTime
= pfdin
->time
;
299 fici
.DosAttribs
= pfdin
->attribs
;
300 memset(&(fici
.FullTargetName
[0]), 0, MAX_PATH
);
301 err
= phsc
->msghandler(phsc
->context
, SPFILENOTIFY_FILEINCABINET
,
302 (UINT
) &fici
, (UINT
) pfdin
->psz1
);
303 if (err
== FILEOP_DOIT
) {
304 TRACE(" Callback specified filename: %s\n", debugstr_a(&(fici
.FullTargetName
[0])));
305 if (!fici
.FullTargetName
[0]) {
306 WARN(" Empty return string causing abort.");
307 SetLastError(ERROR_PATH_NOT_FOUND
);
310 return sc_cb_open(&(fici
.FullTargetName
[0]), _O_BINARY
| _O_CREAT
| _O_WRONLY
, _S_IREAD
| _S_IWRITE
);
312 TRACE(" Callback skipped file.\n");
315 case fdintCLOSE_FILE_INFO
:
316 TRACE("Close file notification\n");
317 /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
318 TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
319 TRACE(" File hndl: %d\n", pfdin->hf); */
320 fp
.Source
= &(phsc
->most_recent_cabinet_name
[0]);
321 fp
.Target
= pfdin
->psz1
;
324 /* the following should be a fixme -- but it occurs too many times */
325 WARN("Should set file date/time/attribs (and execute files?)\n");
326 err
= phsc
->msghandler(phsc
->context
, SPFILENOTIFY_FILEEXTRACTED
, (UINT
) &fp
, 0);
327 if (sc_cb_close(pfdin
->hf
))
328 WARN("_close failed.\n");
334 case fdintNEXT_CABINET
:
335 TRACE("Next cabinet notification\n");
336 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
337 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
338 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
339 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
340 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
341 ci
.CabinetFile
= pfdin
->psz1
;
342 ci
.CabinetPath
= pfdin
->psz3
;
343 ci
.DiskName
= pfdin
->psz2
;
344 ci
.SetId
= pfdin
->setID
;
345 ci
.CabinetNumber
= pfdin
->iCabinet
;
346 /* remember the new cabinet name */
347 strcpy(&(phsc
->most_recent_cabinet_name
[0]), pfdin
->psz1
);
348 err
= phsc
->msghandler(phsc
->context
, SPFILENOTIFY_NEEDNEWCABINET
, (UINT
) &ci
, (UINT
) &(mysterio
[0]));
354 /* some easy paranoia. no such carefulness exists on the wide API IIRC */
355 mysterio
[SIZEOF_MYSTERIO
- 1] = '\0';
356 strncpy(pfdin
->psz3
, &(mysterio
[0]), 255);
357 mysterio
[255] = '\0';
362 FIXME("Unknown notification type %d.\n", fdint
);
367 static INT_PTR
sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint
, PFDINOTIFICATION pfdin
)
369 FILE_IN_CABINET_INFOW fici
;
376 WCHAR mysterio
[SIZEOF_MYSTERIO
]; /* how big? undocumented! */
377 WCHAR buf
[MAX_PATH
], buf2
[MAX_PATH
];
378 CHAR charbuf
[MAX_PATH
];
380 memset(&(mysterio
[0]), 0, SIZEOF_MYSTERIO
* sizeof(WCHAR
));
381 memset(&(buf
[0]), 0, MAX_PATH
* sizeof(WCHAR
));
382 memset(&(buf2
[0]), 0, MAX_PATH
* sizeof(WCHAR
));
383 memset(&(charbuf
[0]), 0, MAX_PATH
);
385 TRACE("(fdint == %d, pfdin == ^%p)\n", fdint
, pfdin
);
387 if (pfdin
&& pfdin
->pv
&& (*((void **) pfdin
->pv
) == (void *)SC_HSC_W_MAGIC
))
388 phsc
= (PSC_HSC_W
) pfdin
->pv
;
390 ERR("pv %p is not an SC_HSC_W.\n", (pfdin
) ? pfdin
->pv
: NULL
);
395 case fdintCABINET_INFO
:
396 TRACE("Cabinet info notification\n");
397 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
398 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
399 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
400 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
401 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
402 WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
403 ci
.CabinetFile
= &(phsc
->most_recent_cabinet_name
[0]);
404 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz3
, -1, &(buf
[0]), MAX_PATH
);
405 if ((len
> MAX_PATH
) || (len
<= 1))
407 ci
.CabinetPath
= &(buf
[0]);
408 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz2
, -1, &(buf2
[0]), MAX_PATH
);
409 if ((len
> MAX_PATH
) || (len
<= 1))
411 ci
.DiskName
= &(buf2
[0]);
412 ci
.SetId
= pfdin
->setID
;
413 ci
.CabinetNumber
= pfdin
->iCabinet
;
414 phsc
->msghandler(phsc
->context
, SPFILENOTIFY_CABINETINFO
, (UINT
) &ci
, 0);
416 case fdintPARTIAL_FILE
:
417 TRACE("Partial file notification\n");
418 /* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
421 TRACE("Copy file notification\n");
422 TRACE(" File name: %s\n", debugstr_a(pfdin
->psz1
));
423 /* TRACE(" File size: %ld\n", pfdin->cb);
424 TRACE(" File date: %u\n", pfdin->date);
425 TRACE(" File time: %u\n", pfdin->time);
426 TRACE(" File attr: %u\n", pfdin->attribs); */
427 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz1
, -1, &(buf2
[0]), MAX_PATH
);
428 if ((len
> MAX_PATH
) || (len
<= 1))
430 fici
.NameInCabinet
= &(buf2
[0]);
431 fici
.FileSize
= pfdin
->cb
;
433 fici
.DosDate
= pfdin
->date
;
434 fici
.DosTime
= pfdin
->time
;
435 fici
.DosAttribs
= pfdin
->attribs
;
436 memset(&(fici
.FullTargetName
[0]), 0, MAX_PATH
* sizeof(WCHAR
));
437 err
= phsc
->msghandler(phsc
->context
, SPFILENOTIFY_FILEINCABINET
,
438 (UINT
) &fici
, (UINT
) pfdin
->psz1
);
439 if (err
== FILEOP_DOIT
) {
440 TRACE(" Callback specified filename: %s\n", debugstr_w(&(fici
.FullTargetName
[0])));
441 if (fici
.FullTargetName
[0]) {
442 len
= strlenW(&(fici
.FullTargetName
[0])) + 1;
443 if ((len
> MAX_PATH
) || (len
<= 1))
445 if (!WideCharToMultiByte(CP_ACP
, 0, &(fici
.FullTargetName
[0]), len
, &(charbuf
[0]), MAX_PATH
, 0, 0))
448 WARN("Empty buffer string caused abort.\n");
449 SetLastError(ERROR_PATH_NOT_FOUND
);
452 return sc_cb_open(&(charbuf
[0]), _O_BINARY
| _O_CREAT
| _O_WRONLY
, _S_IREAD
| _S_IWRITE
);
454 TRACE(" Callback skipped file.\n");
457 case fdintCLOSE_FILE_INFO
:
458 TRACE("Close file notification\n");
459 /* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
460 TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
461 TRACE(" File hndl: %d\n", pfdin->hf); */
462 fp
.Source
= &(phsc
->most_recent_cabinet_name
[0]);
463 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz1
, -1, &(buf
[0]), MAX_PATH
);
464 if ((len
> MAX_PATH
) || (len
<= 1))
466 fp
.Target
= &(buf
[0]);
469 /* a valid fixme -- but occurs too many times */
470 /* FIXME("Should set file date/time/attribs (and execute files?)\n"); */
471 err
= phsc
->msghandler(phsc
->context
, SPFILENOTIFY_FILEEXTRACTED
, (UINT
) &fp
, 0);
472 if (sc_cb_close(pfdin
->hf
))
473 WARN("_close failed.\n");
479 case fdintNEXT_CABINET
:
480 TRACE("Next cabinet notification\n");
481 /* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
482 TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
483 TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
484 TRACE(" Cabinet Set#: %d\n", pfdin->setID);
485 TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
486 /* remember the new cabinet name */
487 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz1
, -1, &(phsc
->most_recent_cabinet_name
[0]), MAX_PATH
);
488 if ((len
> MAX_PATH
) || (len
<= 1))
489 phsc
->most_recent_cabinet_name
[0] = '\0';
490 ci
.CabinetFile
= &(phsc
->most_recent_cabinet_name
[0]);
491 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz3
, -1, &(buf
[0]), MAX_PATH
);
492 if ((len
> MAX_PATH
) || (len
<= 1))
494 ci
.CabinetPath
= &(buf
[0]);
495 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pfdin
->psz2
, -1, &(buf2
[0]), MAX_PATH
);
496 if ((len
> MAX_PATH
) || (len
<= 1))
498 ci
.DiskName
= &(buf2
[0]);
499 ci
.SetId
= pfdin
->setID
;
500 ci
.CabinetNumber
= pfdin
->iCabinet
;
501 err
= phsc
->msghandler(phsc
->context
, SPFILENOTIFY_NEEDNEWCABINET
, (UINT
) &ci
, (UINT
) &(mysterio
[0]));
507 len
= strlenW(&(mysterio
[0])) + 1;
508 if ((len
> 255) || (len
<= 1))
510 if (!WideCharToMultiByte(CP_ACP
, 0, &(mysterio
[0]), len
, pfdin
->psz3
, 255, 0, 0))
516 FIXME("Unknown notification type %d.\n", fdint
);
521 /***********************************************************************
522 * SetupIterateCabinetA (SETUPAPI.@)
524 BOOL WINAPI
SetupIterateCabinetA(PCSTR CabinetFile
, DWORD Reserved
,
525 PSP_FILE_CALLBACK_A MsgHandler
, PVOID Context
)
530 CHAR pszCabinet
[MAX_PATH
], pszCabPath
[MAX_PATH
], *p
;
535 TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n",
536 debugstr_a(CabinetFile
), Reserved
, MsgHandler
, Context
);
538 if (! LoadCABINETDll())
541 memset(&my_hsc
, 0, sizeof(SC_HSC_A
));
542 pszCabinet
[0] = '\0';
543 pszCabPath
[0] = '\0';
545 fpnsize
= strlen(CabinetFile
);
546 if (fpnsize
>= MAX_PATH
) {
547 SetLastError(ERROR_BAD_PATHNAME
);
551 fpnsize
= GetFullPathNameA(CabinetFile
, MAX_PATH
, &(pszCabPath
[0]), &p
);
552 if (fpnsize
> MAX_PATH
) {
553 SetLastError(ERROR_BAD_PATHNAME
);
558 strcpy(pszCabinet
, p
);
561 strcpy(pszCabinet
, CabinetFile
);
562 pszCabPath
[0] = '\0';
565 TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath
), debugstr_a(pszCabinet
));
567 /* remember the cabinet name */
568 strcpy(&(my_hsc
.most_recent_cabinet_name
[0]), pszCabinet
);
570 my_hsc
.magic
= SC_HSC_A_MAGIC
;
571 my_hsc
.msghandler
= MsgHandler
;
572 my_hsc
.context
= Context
;
573 my_hsc
.hfdi
= sc_FDICreate( sc_cb_alloc
, sc_cb_free
, sc_cb_open
, sc_cb_read
,
574 sc_cb_write
, sc_cb_close
, sc_cb_lseek
, cpuUNKNOWN
, &erf
);
576 if (!my_hsc
.hfdi
) return FALSE
;
578 ret
= ( sc_FDICopy(my_hsc
.hfdi
, pszCabinet
, pszCabPath
,
579 0, sc_FNNOTIFY_A
, NULL
, &my_hsc
) ) ? TRUE
: FALSE
;
581 sc_FDIDestroy(my_hsc
.hfdi
);
585 /***********************************************************************
586 * SetupIterateCabinetW (SETUPAPI.@)
588 BOOL WINAPI
SetupIterateCabinetW(PCWSTR CabinetFile
, DWORD Reserved
,
589 PSP_FILE_CALLBACK_W MsgHandler
, PVOID Context
)
591 CHAR CabinetFile_A
[MAX_PATH
];
595 CHAR pszCabinet
[MAX_PATH
], pszCabPath
[MAX_PATH
], *p
;
599 TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n",
600 debugstr_w(CabinetFile
), Reserved
, MsgHandler
, Context
);
602 if (!LoadCABINETDll())
605 if (!CabinetFile
) return FALSE
;
606 if (!WideCharToMultiByte(CP_ACP
, 0, CabinetFile
, -1, CabinetFile_A
, MAX_PATH
, 0, 0))
609 memset(&my_hsc
, 0, sizeof(SC_HSC_W
));
610 pszCabinet
[0] = '\0';
611 pszCabPath
[0] = '\0';
613 fpnsize
= GetFullPathNameA(CabinetFile_A
, MAX_PATH
, &(pszCabPath
[0]), &p
);
614 if (fpnsize
> MAX_PATH
) {
615 SetLastError(ERROR_BAD_PATHNAME
);
620 strcpy(pszCabinet
, p
);
623 strcpy(pszCabinet
, CabinetFile_A
);
624 pszCabPath
[0] = '\0';
627 TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath
), debugstr_a(pszCabinet
));
629 /* remember the cabinet name */
630 len
= 1 + MultiByteToWideChar(CP_ACP
, 0, pszCabinet
, -1,
631 &(my_hsc
.most_recent_cabinet_name
[0]), MAX_PATH
);
635 my_hsc
.most_recent_cabinet_name
[0] = '\0';
636 my_hsc
.magic
= SC_HSC_W_MAGIC
;
637 my_hsc
.msghandler
= MsgHandler
;
638 my_hsc
.context
= Context
;
639 my_hsc
.hfdi
= sc_FDICreate( sc_cb_alloc
, sc_cb_free
, sc_cb_open
, sc_cb_read
,
640 sc_cb_write
, sc_cb_close
, sc_cb_lseek
, cpuUNKNOWN
, &erf
);
642 if (!my_hsc
.hfdi
) return FALSE
;
644 ret
= ( sc_FDICopy(my_hsc
.hfdi
, pszCabinet
, pszCabPath
,
645 0, sc_FNNOTIFY_W
, NULL
, &my_hsc
) ) ? TRUE
: FALSE
;
647 sc_FDIDestroy(my_hsc
.hfdi
);
652 /***********************************************************************
656 * hinstDLL [I] handle to the DLL's instance
658 * lpvReserved [I] reserved, must be NULL
665 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
668 case DLL_PROCESS_ATTACH
:
669 DisableThreadLibraryCalls(hinstDLL
);
671 case DLL_PROCESS_DETACH
: