Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

865 lines
21 KiB

  1. /*++
  2. Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. diamond.c
  5. Abstract:
  6. Implement File Decompression Interface -FDI- for Cabinet files.
  7. Revision History:
  8. 04-20-1999 SamerA Created.
  9. --*/
  10. #include "muisetup.h"
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include <dos.h>
  14. #include <sys/stat.h>
  15. #define STRSAFE_LIB
  16. #include <strsafe.h>
  17. //
  18. // Module Global Variables
  19. //
  20. //
  21. // Cabinet DLL handle
  22. HINSTANCE hCabinetDll;
  23. HFDI ghfdi; // diamond FDI context
  24. //
  25. // DLL Function pointers
  26. //
  27. typedef HFDI (DIAMONDAPI *PFNFDICREATE)(
  28. PFNALLOC pfnalloc,
  29. PFNFREE pfnfree,
  30. PFNOPEN pfnopen,
  31. PFNREAD pfnread,
  32. PFNWRITE pfnwrite,
  33. PFNCLOSE pfnclose,
  34. PFNSEEK pfnseek,
  35. int cpuType,
  36. PERF perf);
  37. typedef BOOL (DIAMONDAPI *PFNFDIISCABINET)(
  38. HFDI hfdi,
  39. INT_PTR hf,
  40. PFDICABINETINFO pfdici);
  41. typedef BOOL (DIAMONDAPI *PFNFDICOPY)(
  42. HFDI hfdi,
  43. char *pszCabinet,
  44. char *pszCabPath,
  45. int flags,
  46. PFNFDINOTIFY pfnfdin,
  47. PFNFDIDECRYPT pfnfdid,
  48. void *pvUser);
  49. typedef BOOL (DIAMONDAPI *PFNFDIDESTROY)(
  50. HFDI hfdi);
  51. PFNFDICREATE pfnFDICreate;
  52. PFNFDICOPY pfnFDICopy;
  53. PFNFDIISCABINET pfnFDIIsCabinet;
  54. PFNFDIDESTROY pfnFDIDestroy;
  55. //-------------------------------------------------------------------------//
  56. // FDI EXTERNAL ROUTINES //
  57. //-------------------------------------------------------------------------//
  58. ////////////////////////////////////////////////////////////////////////////
  59. //
  60. // FDICreate
  61. //
  62. // Tries to create an FDI context. Will load cabinet.dll and hook necessary
  63. // function pointers.
  64. //
  65. // 04-20-99 SamerA Created.
  66. ////////////////////////////////////////////////////////////////////////////
  67. HFDI DIAMONDAPI FDICreate(
  68. PFNALLOC pfnalloc,
  69. PFNFREE pfnfree,
  70. PFNOPEN pfnopen,
  71. PFNREAD pfnread,
  72. PFNWRITE pfnwrite,
  73. PFNCLOSE pfnclose,
  74. PFNSEEK pfnseek,
  75. int cpuType,
  76. PERF perf)
  77. {
  78. HFDI hfdi;
  79. //
  80. // Load cabinet DLL
  81. //
  82. hCabinetDll = LoadLibrary(TEXT("CABINET.DLL"));
  83. if (hCabinetDll == NULL)
  84. {
  85. return NULL;
  86. }
  87. //
  88. // Hook function pointers
  89. //
  90. pfnFDICreate = (PFNFDICREATE) GetProcAddress(hCabinetDll, "FDICreate");
  91. pfnFDICopy = (PFNFDICOPY) GetProcAddress(hCabinetDll, "FDICopy");
  92. pfnFDIIsCabinet = (PFNFDIISCABINET) GetProcAddress(hCabinetDll, "FDIIsCabinet");
  93. pfnFDIDestroy = (PFNFDIDESTROY) GetProcAddress(hCabinetDll, "FDIDestroy");
  94. if ((pfnFDICreate == NULL) ||
  95. (pfnFDICopy == NULL) ||
  96. (pfnFDIIsCabinet == NULL) ||
  97. (pfnFDIDestroy == NULL))
  98. {
  99. FreeLibrary( hCabinetDll );
  100. return NULL;
  101. }
  102. //
  103. // Try to create an FDI context
  104. //
  105. hfdi = pfnFDICreate( pfnalloc,
  106. pfnfree,
  107. pfnopen,
  108. pfnread,
  109. pfnwrite,
  110. pfnclose,
  111. pfnseek,
  112. cpuType,
  113. perf);
  114. if (hfdi == NULL)
  115. {
  116. FreeLibrary(hCabinetDll);
  117. }
  118. return hfdi;
  119. }
  120. ////////////////////////////////////////////////////////////////////////////
  121. //
  122. // FDIIsCabinet
  123. //
  124. // Determines if file is a cabinet, returns info if it is
  125. //
  126. // 04-20-99 SamerA Created.
  127. ////////////////////////////////////////////////////////////////////////////
  128. BOOL DIAMONDAPI FDIIsCabinet(
  129. HFDI hfdi,
  130. INT_PTR hf,
  131. PFDICABINETINFO pfdici)
  132. {
  133. if (pfnFDIIsCabinet == NULL)
  134. {
  135. return FALSE;
  136. }
  137. return (pfnFDIIsCabinet(hfdi,hf,pfdici));
  138. }
  139. ////////////////////////////////////////////////////////////////////////////
  140. //
  141. // FDICopy
  142. //
  143. // Extracts files from a cabinet
  144. //
  145. // 04-20-99 SamerA Created.
  146. ////////////////////////////////////////////////////////////////////////////
  147. BOOL DIAMONDAPI FDICopy(
  148. HFDI hfdi,
  149. char *pszCabinet,
  150. char *pszCabPath,
  151. int flags,
  152. PFNFDINOTIFY pfnfdin,
  153. PFNFDIDECRYPT pfnfdid,
  154. void *pvUser)
  155. {
  156. if (pfnFDICopy == NULL)
  157. {
  158. return FALSE;
  159. }
  160. return (pfnFDICopy(hfdi,pszCabinet,pszCabPath,flags,pfnfdin,pfnfdid,pvUser));
  161. }
  162. ////////////////////////////////////////////////////////////////////////////
  163. //
  164. // FDIDestroy
  165. //
  166. // Destroy an FDI context. Should be called when you're done with the HFDI.
  167. //
  168. // 04-20-99 SamerA Created.
  169. ////////////////////////////////////////////////////////////////////////////
  170. BOOL DIAMONDAPI FDIDestroy(
  171. HFDI hfdi)
  172. {
  173. BOOL bRet;
  174. if (pfnFDIDestroy == NULL)
  175. {
  176. return FALSE;
  177. }
  178. bRet = pfnFDIDestroy( hfdi );
  179. if (bRet == TRUE)
  180. {
  181. FreeLibrary(hCabinetDll);
  182. }
  183. return bRet;
  184. }
  185. //-------------------------------------------------------------------------//
  186. // FDI SUPPORT ROUTINES //
  187. //-------------------------------------------------------------------------//
  188. PVOID
  189. DIAMONDAPI
  190. DiamondMemAlloc(
  191. IN ULONG NumberOfBytes
  192. )
  193. {
  194. return ((PVOID)LocalAlloc(LMEM_FIXED, NumberOfBytes));
  195. }
  196. VOID
  197. DIAMONDAPI
  198. DiamondMemFree(
  199. IN PVOID Block
  200. )
  201. {
  202. if (Block)
  203. {
  204. LocalFree( (HLOCAL)Block );
  205. }
  206. }
  207. INT_PTR
  208. DIAMONDAPI
  209. DiamondFileOpen(
  210. IN PSTR FileName,
  211. IN int oflag,
  212. IN int pmode
  213. )
  214. {
  215. HFILE h;
  216. int OpenMode;
  217. if (oflag & _O_WRONLY)
  218. {
  219. OpenMode = OF_WRITE;
  220. } else
  221. {
  222. if (oflag & _O_RDWR)
  223. {
  224. OpenMode = OF_READWRITE;
  225. } else
  226. {
  227. OpenMode = OF_READ;
  228. }
  229. }
  230. h = _lopen(FileName, OpenMode | OF_SHARE_DENY_WRITE);
  231. if (h == HFILE_ERROR)
  232. {
  233. return -1;
  234. }
  235. return ((INT_PTR) h);
  236. }
  237. UINT
  238. DIAMONDAPI
  239. DiamondFileRead(
  240. IN INT_PTR Handle,
  241. OUT PVOID pv,
  242. IN UINT ByteCount
  243. )
  244. {
  245. UINT rc;
  246. rc = _lread((HFILE)Handle, pv, ByteCount);
  247. if (rc == HFILE_ERROR)
  248. {
  249. rc = (UINT)(-1);
  250. }
  251. return rc;
  252. }
  253. UINT
  254. DIAMONDAPI
  255. DiamondFileWrite(
  256. IN INT_PTR Handle,
  257. IN PVOID pv,
  258. IN UINT ByteCount
  259. )
  260. {
  261. UINT rc;
  262. rc = _lwrite((HFILE)Handle, (LPCSTR)pv, ByteCount);
  263. return rc;
  264. }
  265. int
  266. DIAMONDAPI
  267. DiamondFileClose(
  268. IN INT_PTR Handle
  269. )
  270. {
  271. _lclose( (HFILE)Handle );
  272. return 0;
  273. }
  274. LONG
  275. DIAMONDAPI
  276. DiamondFileSeek(
  277. IN INT_PTR Handle,
  278. IN long Distance,
  279. IN int SeekType
  280. )
  281. {
  282. LONG rc;
  283. rc = _llseek((HFILE)Handle, Distance, SeekType);
  284. if (rc == HFILE_ERROR)
  285. {
  286. rc = -1L;
  287. }
  288. return rc;
  289. }
  290. INT_PTR
  291. DIAMONDAPI
  292. DiamondNotifyFunction(
  293. IN FDINOTIFICATIONTYPE Operation,
  294. IN PFDINOTIFICATION Parameters
  295. )
  296. {
  297. HRESULT hresult;
  298. switch (Operation)
  299. {
  300. case fdintCABINET_INFO: // general information about the cabinet
  301. return 0;
  302. break;
  303. case fdintPARTIAL_FILE: // first file in cabinet is continuation
  304. return 0;
  305. break;
  306. case fdintCOPY_FILE: // file to be copied
  307. {
  308. HFILE handle;
  309. char destination[256];
  310. PDIAMOND_PACKET pDiamond = (PDIAMOND_PACKET) Parameters->pv;
  311. //
  312. // Check to see if we just want the original file name
  313. //
  314. if (pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME)
  315. {
  316. //*STRSAFE* strcpy( pDiamond->szDestFilePath, Parameters->psz1 );
  317. hresult = StringCchCopyA(pDiamond->szDestFilePath , ARRAYSIZE(pDiamond->szDestFilePath), Parameters->psz1 );
  318. if (!SUCCEEDED(hresult))
  319. {
  320. return -1;
  321. }
  322. return 0;
  323. }
  324. //*STRSAFE* sprintf( destination, "%s%s", pDiamond->szDestFilePath, Parameters->psz1 );
  325. hresult = StringCchPrintfA(destination , ARRAYSIZE(destination), "%s%s", pDiamond->szDestFilePath, Parameters->psz1 );
  326. if (!SUCCEEDED(hresult))
  327. {
  328. return -1;
  329. }
  330. handle = _lcreat(destination, 0);
  331. if (handle == HFILE_ERROR)
  332. {
  333. return -1;
  334. }
  335. return handle;
  336. }
  337. break;
  338. case fdintCLOSE_FILE_INFO: // close the file, set relevant info
  339. {
  340. HANDLE handle;
  341. DWORD attrs;
  342. char destination[256];
  343. PDIAMOND_PACKET pDiamond = (PDIAMOND_PACKET) Parameters->pv;
  344. if (pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME)
  345. {
  346. return 0;
  347. }
  348. //*STRSAFE* sprintf( destination, "%s%s", pDiamond->szDestFilePath, Parameters->psz1);
  349. hresult = StringCchPrintfA(destination , ARRAYSIZE(destination), "%s%s", pDiamond->szDestFilePath, Parameters->psz1);
  350. if (!SUCCEEDED(hresult))
  351. {
  352. return -1;
  353. }
  354. _lclose( (HFILE)Parameters->hf );
  355. //
  356. // Set date/time
  357. //
  358. // Need Win32 type handle for to set date/time
  359. //
  360. handle = CreateFileA( destination,
  361. GENERIC_READ | GENERIC_WRITE,
  362. FILE_SHARE_READ,
  363. NULL,
  364. OPEN_EXISTING,
  365. FILE_ATTRIBUTE_NORMAL,
  366. NULL
  367. );
  368. if (handle != INVALID_HANDLE_VALUE)
  369. {
  370. FILETIME datetime;
  371. if (TRUE == DosDateTimeToFileTime( Parameters->date,
  372. Parameters->time,
  373. &datetime))
  374. {
  375. FILETIME local_filetime;
  376. if (TRUE == LocalFileTimeToFileTime( &datetime,
  377. &local_filetime))
  378. {
  379. SetFileTime( handle,
  380. &local_filetime,
  381. NULL,
  382. &local_filetime
  383. );
  384. }
  385. }
  386. CloseHandle(handle);
  387. }
  388. //
  389. // Mask out attribute bits other than readonly,
  390. // hidden, system, and archive, since the other
  391. // attribute bits are reserved for use by
  392. // the cabinet format.
  393. //
  394. attrs = Parameters->attribs;
  395. attrs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
  396. SetFileAttributesA( destination,
  397. attrs
  398. );
  399. return TRUE;
  400. }
  401. break;
  402. case fdintNEXT_CABINET: // file continued to next cabinet
  403. return 0;
  404. break;
  405. }
  406. return 0;
  407. }
  408. //-------------------------------------------------------------------------//
  409. // MUISETUP-SUPPORT ROUTINES //
  410. //-------------------------------------------------------------------------//
  411. ////////////////////////////////////////////////////////////////////////////
  412. //
  413. // Muisetup_InitDiamond
  414. //
  415. // Initialize diamond DLL.
  416. //
  417. // 04-23-99 SamerA Created.
  418. ////////////////////////////////////////////////////////////////////////////
  419. HFDI Muisetup_InitDiamond()
  420. {
  421. ERF erf;
  422. if (!ghfdi)
  423. {
  424. ghfdi = FDICreate( DiamondMemAlloc,
  425. DiamondMemFree,
  426. DiamondFileOpen,
  427. DiamondFileRead,
  428. DiamondFileWrite,
  429. DiamondFileClose,
  430. DiamondFileSeek,
  431. cpuUNKNOWN,
  432. &erf );
  433. }
  434. return ghfdi;
  435. }
  436. ////////////////////////////////////////////////////////////////////////////
  437. //
  438. // Muisetup_FreeDiamond
  439. //
  440. // Free diamond dll. Should be called at application shutdown.
  441. //
  442. // 04-23-99 SamerA Created.
  443. ////////////////////////////////////////////////////////////////////////////
  444. BOOL Muisetup_FreeDiamond()
  445. {
  446. BOOL bRet = TRUE;
  447. if (ghfdi)
  448. {
  449. bRet = FDIDestroy(ghfdi);
  450. }
  451. return bRet;
  452. }
  453. ////////////////////////////////////////////////////////////////////////////
  454. //
  455. // Muisetup_DiamondReset
  456. //
  457. // Should be called at the start of processing a file to copy.
  458. //
  459. // 04-23-99 SamerA Created.
  460. ////////////////////////////////////////////////////////////////////////////
  461. void Muisetup_DiamondReset(
  462. PDIAMOND_PACKET pDiamond)
  463. {
  464. pDiamond->flags = DIAMOND_NONE;
  465. return;
  466. }
  467. ////////////////////////////////////////////////////////////////////////////
  468. //
  469. // Muisetup_IsDiamondFile
  470. //
  471. // Determines if a file is a diamond file, and if so, returns its original
  472. // name.
  473. //
  474. // 04-23-99 SamerA Created.
  475. ////////////////////////////////////////////////////////////////////////////
  476. BOOL Muisetup_IsDiamondFile(
  477. PWSTR pwszFileName,
  478. PWSTR pwszOriginalName,
  479. INT nSize,
  480. PDIAMOND_PACKET pDiamond)
  481. {
  482. INT_PTR hf;
  483. BOOL bRet;
  484. int nCount;
  485. char *p;
  486. FDICABINETINFO fdici;
  487. HFDI hfdi = ghfdi;
  488. HRESULT hresult;
  489. if (!hfdi)
  490. {
  491. #if SAMER_DBG
  492. OutputDebugStringA("Muisetup_IsDiamondFile : No HFDI context\n");
  493. #endif
  494. return FALSE;
  495. }
  496. //
  497. // Init the diamond packet
  498. //
  499. pDiamond->flags = DIAMOND_NONE;
  500. if ((nCount = WideCharToMultiByte( CP_ACP,
  501. 0,
  502. pwszFileName,
  503. -1,
  504. pDiamond->szSrcFilePath,
  505. sizeof( pDiamond->szSrcFilePath ),
  506. NULL,
  507. NULL )) == 0)
  508. {
  509. #if SAMER_DBG
  510. OutputDebugStringA("Muisetup_IsDiamondFile : WideCharToMultiByte failed\n");
  511. #endif
  512. return FALSE;
  513. }
  514. pDiamond->szSrcFilePath[ nCount ] = '\0';
  515. hf = DiamondFileOpen( pDiamond->szSrcFilePath,
  516. _O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
  517. 0
  518. );
  519. if (hf == -1)
  520. {
  521. #if SAMER_DBG
  522. OutputDebugStringA("Muisetup_IsDiamondFile : file_open failed\n");
  523. #endif
  524. return FALSE;
  525. }
  526. bRet = FDIIsCabinet( hfdi,
  527. hf,
  528. &fdici
  529. );
  530. DiamondFileClose( hf );
  531. //
  532. // If succeeded, then let's setup everything else
  533. // to get the correct original file name
  534. //
  535. if (bRet)
  536. {
  537. pDiamond->flags |= DIAMOND_GET_DEST_FILE_NAME;
  538. p = strrchr(pDiamond->szSrcFilePath, '\\');
  539. if (p == NULL)
  540. {
  541. //*STRSAFE* strcpy(pDiamond->szSrcFileName, pDiamond->szSrcFilePath);
  542. hresult = StringCchCopyA(pDiamond->szSrcFileName , ARRAYSIZE(pDiamond->szSrcFileName), pDiamond->szSrcFilePath);
  543. if (!SUCCEEDED(hresult))
  544. {
  545. return FALSE;
  546. }
  547. //*STRSAFE* strcpy(pDiamond->szSrcFilePath, "");
  548. hresult = StringCchCopyA(pDiamond->szSrcFilePath , ARRAYSIZE(pDiamond->szSrcFilePath), "");
  549. if (!SUCCEEDED(hresult))
  550. {
  551. return FALSE;
  552. }
  553. }
  554. else
  555. {
  556. //*STRSAFE* strcpy(pDiamond->szSrcFileName, p+1);
  557. hresult = StringCchCopyA(pDiamond->szSrcFileName , ARRAYSIZE(pDiamond->szSrcFileName), p+1);
  558. if (!SUCCEEDED(hresult))
  559. {
  560. return FALSE;
  561. }
  562. p[ 1 ] = '\0';
  563. }
  564. //*STRSAFE* strcpy( pDiamond->szDestFilePath, "c:\\samer\\" );
  565. hresult = StringCchCopyA(pDiamond->szDestFilePath , ARRAYSIZE(pDiamond->szDestFilePath), "c:\\samer\\" );
  566. if (!SUCCEEDED(hresult))
  567. {
  568. return FALSE;
  569. }
  570. if (Muisetup_CopyDiamondFile( pDiamond,
  571. NULL))
  572. {
  573. //
  574. // Convert the original file name back to Unicode
  575. //
  576. nCount = MultiByteToWideChar( CP_ACP,
  577. 0,
  578. pDiamond->szDestFilePath,
  579. -1,
  580. pwszOriginalName,
  581. nSize
  582. );
  583. if (!nCount)
  584. {
  585. return FALSE;
  586. }
  587. pwszOriginalName[ nCount ] = UNICODE_NULL;
  588. pDiamond->flags = DIAMOND_FILE;
  589. #if SAMER_DBG
  590. {
  591. BYTE byBuf[200];
  592. //*STRSAFE* wsprintfA(byBuf, "SrcFile = %s%s, OriginalFileName=%s\n", pDiamond->szSrcFilePath, pDiamond->szSrcFileName,pDiamond->szDestFilePath);
  593. hresult = StringCchPrintfA(byBuf , ARRAYSIZE(byBuf), "SrcFile = %s%s, OriginalFileName=%s\n", pDiamond->szSrcFilePath, pDiamond->szSrcFileName,pDiamond->szDestFilePath);
  594. if (!SUCCEEDED(hresult))
  595. {
  596. return FALSE;
  597. }
  598. OutputDebugStringA(byBuf);
  599. }
  600. #endif
  601. }
  602. pDiamond->flags &= ~DIAMOND_GET_DEST_FILE_NAME;
  603. }
  604. return bRet;
  605. }
  606. ////////////////////////////////////////////////////////////////////////////
  607. //
  608. // Muisetup_CopyDiamondFile
  609. //
  610. // Copies and expands a diamond file.
  611. //
  612. // 04-23-99 SamerA Created.
  613. ////////////////////////////////////////////////////////////////////////////
  614. BOOL Muisetup_CopyDiamondFile(
  615. PDIAMOND_PACKET pDiamond,
  616. PWSTR pwszCopyTo)
  617. {
  618. char szDestPath[ MAX_PATH + 1];
  619. char *p;
  620. int nCount;
  621. BOOL bRet;
  622. HFDI hfdi = ghfdi;
  623. HRESULT hresult;
  624. //
  625. // Validate that this is a diamond file
  626. //
  627. if ((!hfdi) ||
  628. (pDiamond->flags == DIAMOND_NONE))
  629. {
  630. return FALSE;
  631. }
  632. //
  633. // Validate flags
  634. //
  635. if (!(pDiamond->flags & (DIAMOND_FILE | DIAMOND_GET_DEST_FILE_NAME)))
  636. {
  637. return FALSE;
  638. }
  639. #if SAMER_DBG
  640. {
  641. BYTE byBuf[100];
  642. //*STRSAFE* wsprintfA(byBuf, "DiamondCopy called for %s, flags = %lx\n", pDiamond->szSrcFileName, pDiamond->flags);
  643. hresult = StringCchPrintfA(byBuf , ARRAYSIZE(byBuf), "DiamondCopy called for %s, flags = %lx\n", pDiamond->szSrcFileName, pDiamond->flags);
  644. if (!SUCCEEDED(hresult))
  645. {
  646. return FALSE;
  647. }
  648. OutputDebugStringA(byBuf);
  649. }
  650. #endif
  651. if (!(pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME))
  652. {
  653. if ((nCount = WideCharToMultiByte( CP_ACP,
  654. 0,
  655. pwszCopyTo,
  656. -1,
  657. szDestPath,
  658. sizeof( szDestPath ),
  659. NULL,
  660. NULL )) == 0)
  661. {
  662. return FALSE;
  663. }
  664. p = strrchr(szDestPath, '\\');
  665. if (p)
  666. {
  667. p[1] = '\0';
  668. }
  669. else
  670. {
  671. szDestPath[ nCount ] = '\\';
  672. szDestPath[ nCount + 1 ] = '\0';
  673. }
  674. //*STRSAFE* strcpy( pDiamond->szDestFilePath, szDestPath );
  675. hresult = StringCchCopyA(pDiamond->szDestFilePath , ARRAYSIZE(pDiamond->szDestFilePath), szDestPath );
  676. if (!SUCCEEDED(hresult))
  677. {
  678. return FALSE;
  679. }
  680. }
  681. bRet = FDICopy( hfdi,
  682. pDiamond->szSrcFileName,
  683. pDiamond->szSrcFilePath,
  684. 0,
  685. DiamondNotifyFunction,
  686. NULL,
  687. pDiamond);
  688. #if SAMER_DBG
  689. {
  690. BYTE byBuf[200];
  691. //*STRSAFE* wsprintfA(byBuf, "SrcFile = %s%s, DestPath=%s, Status=%lx\n", pDiamond->szSrcFilePath,pDiamond->szSrcFileName,pDiamond->szDestFilePath, bRet);
  692. hresult = StringCchPrintfA(byBuf , ARRAYSIZE(byBuf), "SrcFile = %s%s, DestPath=%s, Status=%lx\n", pDiamond->szSrcFilePath,pDiamond->szSrcFileName,pDiamond->szDestFilePath, bRet);
  693. if (!SUCCEEDED(hresult))
  694. {
  695. return FALSE;
  696. }
  697. OutputDebugStringA(byBuf);
  698. }
  699. #endif
  700. return bRet;
  701. }