Source code of Windows XP (NT5)
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.

972 lines
22 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. patchdll.c
  5. Abstract:
  6. This file contains the patchdll entry points for the Windows NT Patch
  7. Utility.
  8. Author:
  9. Sunil Pai (sunilp) Aug 1993
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <stdlib.h>
  18. #include "rc_ids.h"
  19. #include "patchdll.h"
  20. CHAR ReturnTextBuffer[ RETURN_BUFFER_SIZE ];
  21. //
  22. // Entry Point to Change the File Attributes of a list of files
  23. //
  24. BOOL
  25. ChangeFileAttributes(
  26. IN DWORD cArgs,
  27. IN LPSTR Args[],
  28. OUT LPSTR *TextOut
  29. )
  30. {
  31. DWORD Attribs = 0;
  32. CHAR *ptr = Args[0];
  33. *TextOut = ReturnTextBuffer;
  34. if(cArgs != 2) {
  35. SetErrorText(IDS_ERROR_BADARGS);
  36. return(FALSE);
  37. }
  38. //
  39. // Determine what the file attributes to set by examining args[0]
  40. //
  41. while(*ptr) {
  42. switch(*ptr) {
  43. case 'S':
  44. case 's':
  45. Attribs |= FILE_ATTRIBUTE_SYSTEM;
  46. break;
  47. case 'A':
  48. case 'a':
  49. Attribs |= FILE_ATTRIBUTE_ARCHIVE;
  50. break;
  51. case 'H':
  52. case 'h':
  53. Attribs |= FILE_ATTRIBUTE_HIDDEN;
  54. break;
  55. case 'R':
  56. case 'r':
  57. Attribs |= FILE_ATTRIBUTE_READONLY;
  58. break;
  59. case 'T':
  60. case 't':
  61. Attribs |= FILE_ATTRIBUTE_TEMPORARY;
  62. break;
  63. default:
  64. Attribs |= FILE_ATTRIBUTE_NORMAL;
  65. }
  66. ptr++;
  67. }
  68. //
  69. // Find the file and set the new attribs
  70. //
  71. if(FFileFound( Args[1] ) && SetFileAttributes( Args[1], Attribs ) ) {
  72. SetReturnText( "YES" );
  73. } else {
  74. SetReturnText( "NO" );
  75. }
  76. return ( TRUE );
  77. }
  78. //
  79. // Entry point to check build version we are installing on is not greater
  80. // than our patch build version.
  81. //
  82. BOOL
  83. CheckBuildVersion(
  84. IN DWORD cArgs,
  85. IN LPSTR Args[],
  86. OUT LPSTR *TextOut
  87. )
  88. {
  89. DWORD dwPatch, dwCurVer;
  90. CHAR VersionString[16];
  91. *TextOut = ReturnTextBuffer;
  92. dwCurVer = (GetVersion() & 0x7fff0000) >> 16;
  93. wsprintf( VersionString, "%d", dwCurVer );
  94. SetReturnText( VersionString );
  95. return ( TRUE );
  96. }
  97. //
  98. // Entry point to find out if a file is opened with exclusive access
  99. //
  100. BOOL
  101. IsFileOpenedExclusive(
  102. IN DWORD cArgs,
  103. IN LPSTR Args[],
  104. OUT LPSTR *TextOut
  105. )
  106. {
  107. OFSTRUCT ofstruct;
  108. HFILE hFile;
  109. *TextOut = ReturnTextBuffer;
  110. if(cArgs != 1) {
  111. SetErrorText(IDS_ERROR_BADARGS);
  112. return(FALSE);
  113. }
  114. SetReturnText( "NO" );
  115. if ( FFileFound( Args[0] ) ) {
  116. SetFileAttributes( Args[0], FILE_ATTRIBUTE_NORMAL );
  117. if( (hFile = OpenFile( Args[0], &ofstruct, OF_READ | OF_WRITE )) == HFILE_ERROR ) {
  118. CHAR TempPath[MAX_PATH];
  119. CHAR TempName[MAX_PATH];
  120. CHAR *LastSlash;
  121. //
  122. // Can the file be renamed - generate a temporary name and try
  123. // renaming it to this name. If it works rename it back to the
  124. // old name.
  125. //
  126. lstrcpy (TempPath, Args[0]);
  127. LastSlash = strrchr( TempPath, '\\' );
  128. *LastSlash = '\0';
  129. if (GetTempFileName( TempPath, "temp", 0, TempName) == 0 ) {
  130. SetErrorText( IDS_ERROR_GENERATETEMP );
  131. return( FALSE );
  132. }
  133. else {
  134. DeleteFile( TempName );
  135. }
  136. if ( MoveFile ( Args[0], TempName ) ) {
  137. MoveFile( TempName, Args[0] );
  138. }
  139. else {
  140. SetReturnText( "YES" );
  141. }
  142. }
  143. else {
  144. CloseHandle( LongToHandle(hFile) );
  145. }
  146. }
  147. return ( TRUE );
  148. }
  149. //
  150. // Entry point to generate a temporary file name
  151. //
  152. // Args[0] : Directory to create temporary file name in
  153. //
  154. BOOL
  155. GenerateTemporary(
  156. IN DWORD cArgs,
  157. IN LPSTR Args[],
  158. OUT LPSTR *TextOut
  159. )
  160. {
  161. CHAR TempFile[ MAX_PATH ];
  162. CHAR *sz;
  163. *TextOut = ReturnTextBuffer;
  164. if(cArgs != 1) {
  165. SetErrorText(IDS_ERROR_BADARGS);
  166. return(FALSE);
  167. }
  168. if (GetTempFileName( Args[0], "temp", 0, TempFile) == 0 ) {
  169. SetErrorText( IDS_ERROR_GENERATETEMP );
  170. return( FALSE );
  171. }
  172. if (sz = strrchr( TempFile, '\\')) {
  173. sz++;
  174. SetReturnText(sz);
  175. }
  176. else {
  177. SetReturnText( TempFile );
  178. }
  179. return( TRUE );
  180. }
  181. //
  182. // Entry point to implement the MoveFileEx functionality to copy the file
  183. // on reboot.
  184. //
  185. BOOL
  186. CopyFileOnReboot(
  187. IN DWORD cArgs,
  188. IN LPSTR Args[],
  189. OUT LPSTR *TextOut
  190. )
  191. {
  192. CHAR Root[] = "?:\\";
  193. DWORD dw1, dw2;
  194. CHAR VolumeFSName[MAX_PATH];
  195. *TextOut = ReturnTextBuffer;
  196. if(cArgs < 2) {
  197. SetErrorText(IDS_ERROR_BADARGS);
  198. return(FALSE);
  199. }
  200. //
  201. // First Copy the security from Args[1] to Args[0] if it is on NTFS volume
  202. //
  203. Root[0] = Args[1][0];
  204. if(!GetVolumeInformation( Root, NULL, 0, NULL, &dw1, &dw2, VolumeFSName, MAX_PATH )) {
  205. SetErrorText(IDS_ERROR_GETVOLINFO);
  206. return(FALSE);
  207. }
  208. if(!lstrcmpi( VolumeFSName, "NTFS" )) {
  209. if(!FTransferSecurity( Args[1], Args[0] )) {
  210. SetErrorText(IDS_ERROR_TRANSFERSEC);
  211. return( FALSE );
  212. }
  213. }
  214. if ( MoveFileEx(
  215. Args[0],
  216. Args[1],
  217. MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT
  218. )
  219. ) {
  220. SetReturnText( "SUCCESS" );
  221. }
  222. else {
  223. SetReturnText("FAILURE");
  224. }
  225. return( TRUE );
  226. }
  227. //
  228. // SUBROUTINES
  229. //
  230. //
  231. // Entry point to search the setup.log file to determine the hal, kernel and
  232. // boot scsi types.
  233. //
  234. // 1. Arg[0]: List of files whose source files are to be determined: eg.
  235. // {hal.dll, ntoskrnl.exe, ntbootdd.sys}
  236. BOOL
  237. GetFileTypes(
  238. IN DWORD cArgs,
  239. IN LPSTR Args[],
  240. OUT LPSTR *TextOut
  241. )
  242. {
  243. CHAR SetupLogFile[ MAX_PATH ];
  244. DWORD nFiles, i, dwAttr = FILE_ATTRIBUTE_NORMAL;
  245. BOOL Status = TRUE;
  246. RGSZ FilesArray = NULL, FilesTypeArray = NULL;
  247. PCHAR sz1, sz4;
  248. PCHAR SectionNames = NULL;
  249. ULONG BufferSizeForSectionNames;
  250. PCHAR CurrentSectionName;
  251. ULONG Count;
  252. CHAR TmpFileName[ MAX_PATH + 1 ];
  253. //
  254. // Validate the argument passed in
  255. //
  256. *TextOut = ReturnTextBuffer;
  257. if(cArgs != 1) {
  258. SetErrorText(IDS_ERROR_BADARGS);
  259. return(FALSE);
  260. }
  261. *ReturnTextBuffer = '\0';
  262. //
  263. // Get the windows directory, check to see if the setup.log file is there
  264. // and if not present, return
  265. //
  266. if (!GetWindowsDirectory( SetupLogFile, MAX_PATH )) {
  267. SetErrorText(IDS_ERROR_GETWINDOWSDIR);
  268. return( FALSE );
  269. }
  270. strcat( SetupLogFile, "\\repair\\setup.log" );
  271. if( !FFileFound ( SetupLogFile ) ) {
  272. SetReturnText( "SETUPLOGNOTPRESENT" );
  273. return( TRUE );
  274. }
  275. //
  276. // Take the lists passed in and convert them into C Pointer Arrays.
  277. //
  278. if ((FilesArray = RgszFromSzListValue(Args[0])) == NULL ) {
  279. Status = FALSE;
  280. SetErrorText(IDS_ERROR_DLLOOM);
  281. goto r0;
  282. }
  283. nFiles = RgszCount( FilesArray );
  284. //
  285. // Form return types rgsz
  286. //
  287. if( !(FilesTypeArray = RgszAlloc( nFiles + 1 )) ) {
  288. Status = FALSE;
  289. SetErrorText(IDS_ERROR_DLLOOM);
  290. goto r0;
  291. }
  292. for ( i = 0; i < nFiles; i++ ) {
  293. if( !(FilesTypeArray[i] = SzDup( "" )) ) {
  294. Status = FALSE;
  295. SetErrorText(IDS_ERROR_DLLOOM);
  296. goto r1;
  297. }
  298. }
  299. //
  300. // Set the attributes on the file to normal attributes
  301. //
  302. if ( dwAttr = GetFileAttributes( SetupLogFile ) == 0xFFFFFFFF ) {
  303. Status = FALSE;
  304. SetErrorText(IDS_ERROR_GETATTRIBUTES);
  305. goto r1;
  306. }
  307. SetFileAttributes( SetupLogFile, FILE_ATTRIBUTE_NORMAL );
  308. BufferSizeForSectionNames = BUFFER_SIZE;
  309. SectionNames = ( PCHAR )MyMalloc( BufferSizeForSectionNames );
  310. if( SectionNames == NULL ) {
  311. Status = FALSE;
  312. SetErrorText(IDS_ERROR_DLLOOM);
  313. goto r2;
  314. }
  315. //
  316. // Find out the names of all sections in setup.log
  317. //
  318. while( ( Count = GetPrivateProfileString( NULL,
  319. "",
  320. "",
  321. SectionNames,
  322. BufferSizeForSectionNames,
  323. SetupLogFile ) ) == BufferSizeForSectionNames - 2 ) {
  324. if( Count == 0 ) {
  325. Status = FALSE;
  326. SetErrorText( IDS_ERROR_READLOGFILE );
  327. goto r2;
  328. }
  329. BufferSizeForSectionNames += BUFFER_SIZE;
  330. SectionNames = ( PCHAR )MyRealloc( SectionNames, BufferSizeForSectionNames );
  331. if( SectionNames == NULL ) {
  332. Status = FALSE;
  333. SetErrorText(IDS_ERROR_DLLOOM);
  334. goto r1;
  335. }
  336. }
  337. for (i = 0; i < nFiles; i++) {
  338. for( CurrentSectionName = SectionNames;
  339. *CurrentSectionName != '\0';
  340. CurrentSectionName += lstrlen( CurrentSectionName ) + 1 ) {
  341. //
  342. // If the file is supposed to be found in [Files.WinNt] section,
  343. // then use as key name, the full path without the drive letter.
  344. // If the file is supposed to be found in [Files.SystemPartition]
  345. // section, then use as key name the filename only.
  346. // Note that one or neither call to GetPrivateProfileString API
  347. // will succeed. It is necessary to make the two calls, since the
  348. // files logged in [Files.WinNt] and [Files.SystemPartition] have
  349. // different formats.
  350. //
  351. if( ( ( GetPrivateProfileString( CurrentSectionName,
  352. strchr( FilesArray[i], ':' ) + 1,
  353. "",
  354. TmpFileName,
  355. sizeof( TmpFileName ),
  356. SetupLogFile ) > 0 ) ||
  357. ( GetPrivateProfileString( CurrentSectionName,
  358. strrchr( FilesArray[i], '\\' ) + 1,
  359. "",
  360. TmpFileName,
  361. sizeof( TmpFileName ),
  362. SetupLogFile ) > 0 )
  363. ) &&
  364. ( lstrlen( TmpFileName ) != 0 ) ) {
  365. if ( sz1 = strchr( TmpFileName, ',' )) {
  366. *sz1 = '\0';
  367. if( sz1 = strchr( TmpFileName, '.' )) {
  368. *sz1 = '\0';
  369. }
  370. if( !(sz1 = SzDup( TmpFileName )) ) {
  371. Status = FALSE;
  372. SetErrorText(IDS_ERROR_DLLOOM);
  373. goto r2;
  374. }
  375. MyFree( FilesTypeArray[i] );
  376. FilesTypeArray[i] = sz1;
  377. break;
  378. }
  379. }
  380. }
  381. }
  382. //
  383. // Convert the rgsz into a list
  384. //
  385. if( !(sz4 = SzListValueFromRgsz( FilesTypeArray ))) {
  386. Status = FALSE;
  387. SetErrorText(IDS_ERROR_DLLOOM);
  388. }
  389. else {
  390. SetReturnText( sz4 );
  391. MyFree( sz4 );
  392. }
  393. r2:
  394. SetFileAttributes( SetupLogFile, dwAttr );
  395. r1:
  396. //
  397. // Free pointers allocated
  398. //
  399. if ( FilesTypeArray ) {
  400. RgszFree( FilesTypeArray );
  401. }
  402. if ( FilesArray ) {
  403. RgszFree( FilesArray );
  404. }
  405. if( SectionNames ) {
  406. MyFree( ( PVOID )SectionNames );
  407. }
  408. r0:
  409. return( Status );
  410. }
  411. //*************************************************************************
  412. //
  413. // MEMORY MANAGEMENT
  414. //
  415. //*************************************************************************
  416. PVOID
  417. MyMalloc(
  418. size_t Size
  419. )
  420. {
  421. return (PVOID)LocalAlloc( 0, Size );
  422. }
  423. VOID
  424. MyFree(
  425. PVOID p
  426. )
  427. {
  428. LocalFree( (HANDLE)p );
  429. }
  430. PVOID
  431. MyRealloc(
  432. PVOID p,
  433. size_t Size
  434. )
  435. {
  436. return (PVOID)LocalReAlloc( p, Size, LMEM_MOVEABLE );
  437. }
  438. //*************************************************************************
  439. //
  440. // LIST MANIPULATION
  441. //
  442. //*************************************************************************
  443. /*
  444. ** Purpose:
  445. ** Determines if a string is a list value.
  446. ** Arguments:
  447. ** szValue: non-NULL, zero terminated string to be tested.
  448. ** Returns:
  449. ** fTrue if a list; fFalse otherwise.
  450. **
  451. **************************************************************************/
  452. BOOL FListValue(szValue)
  453. SZ szValue;
  454. {
  455. if (*szValue++ != '{')
  456. return(fFalse);
  457. while (*szValue != '}' && *szValue != '\0')
  458. {
  459. if (*szValue++ != '"')
  460. return(fFalse);
  461. while (*szValue != '\0')
  462. {
  463. if (*szValue != '"')
  464. szValue = SzNextChar(szValue);
  465. else if (*(szValue + 1) == '"')
  466. szValue += 2;
  467. else
  468. break;
  469. }
  470. if (*szValue++ != '"')
  471. return(fFalse);
  472. if (*szValue == ',')
  473. if (*(++szValue) == '}')
  474. return(fFalse);
  475. }
  476. if (*szValue != '}')
  477. return(fFalse);
  478. return(fTrue);
  479. }
  480. RGSZ
  481. RgszAlloc(
  482. DWORD Size
  483. )
  484. {
  485. RGSZ rgsz = NULL;
  486. DWORD i;
  487. if ( Size > 0 ) {
  488. if ( (rgsz = MyMalloc( Size * sizeof(SZ) )) ) {
  489. for ( i=0; i<Size; i++ ) {
  490. rgsz[i] = NULL;
  491. }
  492. }
  493. }
  494. return rgsz;
  495. }
  496. VOID
  497. RgszFree(
  498. RGSZ rgsz
  499. )
  500. {
  501. INT i;
  502. for (i = 0; rgsz[i]; i++ ) {
  503. MyFree( rgsz[i] );
  504. }
  505. MyFree(rgsz);
  506. }
  507. /*
  508. ** Purpose:
  509. ** Converts a list value into an RGSZ.
  510. ** Arguments:
  511. ** szListValue: non-NULL, zero terminated string to be converted.
  512. ** Returns:
  513. ** NULL if an error occurred.
  514. ** Non-NULL RGSZ if the conversion was successful.
  515. **
  516. **************************************************************************/
  517. RGSZ RgszFromSzListValue(szListValue)
  518. SZ szListValue;
  519. {
  520. USHORT cItems;
  521. SZ szCur;
  522. RGSZ rgsz;
  523. if (!FListValue(szListValue))
  524. {
  525. if ((rgsz = (RGSZ)MyMalloc((CB)(2 * sizeof(SZ)))) == (RGSZ)NULL ||
  526. (rgsz[0] = SzDup(szListValue)) == (SZ)NULL)
  527. return((RGSZ)NULL);
  528. rgsz[1] = (SZ)NULL;
  529. return(rgsz);
  530. }
  531. if ((rgsz = (RGSZ)MyMalloc((CB)((cListItemsMax + 1) * sizeof(SZ)))) ==
  532. (RGSZ)NULL)
  533. return((RGSZ)NULL);
  534. cItems = 0;
  535. szCur = szListValue + 1;
  536. while (*szCur != '}' &&
  537. *szCur != '\0' &&
  538. cItems < cListItemsMax)
  539. {
  540. SZ szValue;
  541. SZ szAddPoint;
  542. if( *szCur != '"' ) {
  543. return( (RGSZ) NULL );
  544. }
  545. szCur++;
  546. if ((szAddPoint = szValue = (SZ)MyMalloc(cbItemMax)) == (SZ)NULL)
  547. {
  548. rgsz[cItems] = (SZ)NULL;
  549. RgszFree(rgsz);
  550. return((RGSZ)NULL);
  551. }
  552. while (*szCur != '\0')
  553. {
  554. if (*szCur == '"')
  555. {
  556. if (*(szCur + 1) != '"')
  557. break;
  558. szCur += 2;
  559. *szAddPoint++ = '"';
  560. }
  561. else
  562. {
  563. SZ szNext = SzNextChar(szCur);
  564. while (szCur < szNext)
  565. *szAddPoint++ = *szCur++;
  566. }
  567. }
  568. *szAddPoint = '\0';
  569. if (*szCur++ != '"' ||
  570. lstrlen(szValue) >= cbItemMax ||
  571. (szAddPoint = SzDup(szValue)) == (SZ)NULL)
  572. {
  573. MyFree((PB)szValue);
  574. rgsz[cItems] = (SZ)NULL;
  575. RgszFree(rgsz);
  576. return((RGSZ)NULL);
  577. }
  578. MyFree((PB)szValue);
  579. if (*szCur == ',')
  580. szCur++;
  581. rgsz[cItems++] = szAddPoint;
  582. }
  583. rgsz[cItems] = (SZ)NULL;
  584. if (*szCur != '}' || cItems >= cListItemsMax)
  585. {
  586. RgszFree(rgsz);
  587. return((RGSZ)NULL);
  588. }
  589. if (cItems < cListItemsMax)
  590. rgsz = (RGSZ)MyRealloc((PB)rgsz, (CB)((cItems + 1) * sizeof(SZ)));
  591. return(rgsz);
  592. }
  593. /*
  594. ** Purpose:
  595. ** Converts an RGSZ into a list value.
  596. ** Arguments:
  597. ** rgsz: non-NULL, NULL-terminated array of zero-terminated strings to
  598. ** be converted.
  599. ** Returns:
  600. ** NULL if an error occurred.
  601. ** Non-NULL SZ if the conversion was successful.
  602. **
  603. **************************************************************************/
  604. SZ SzListValueFromRgsz(rgsz)
  605. RGSZ rgsz;
  606. {
  607. SZ szValue;
  608. SZ szAddPoint;
  609. SZ szItem;
  610. BOOL fFirstItem = fTrue;
  611. //ChkArg(rgsz != (RGSZ)NULL, 1, (SZ)NULL);
  612. if ((szAddPoint = szValue = (SZ)MyMalloc(cbItemMax)) == (SZ)NULL)
  613. return((SZ)NULL);
  614. *szAddPoint++ = '{';
  615. while ((szItem = *rgsz) != (SZ)NULL)
  616. {
  617. if (fFirstItem)
  618. fFirstItem = fFalse;
  619. else
  620. *szAddPoint++ = ',';
  621. *szAddPoint++ = '"';
  622. while (*szItem != '\0')
  623. {
  624. if (*szItem == '"')
  625. {
  626. *szAddPoint++ = '"';
  627. *szAddPoint++ = '"';
  628. szItem++;
  629. }
  630. else
  631. {
  632. SZ szNext = SzNextChar(szItem);
  633. while (szItem < szNext)
  634. *szAddPoint++ = *szItem++;
  635. }
  636. }
  637. *szAddPoint++ = '"';
  638. rgsz++;
  639. }
  640. *szAddPoint++ = '}';
  641. *szAddPoint = '\0';
  642. //AssertRet(CbStrLen(szValue) < cbItemMax, (SZ)NULL);
  643. szItem = SzDup(szValue);
  644. MyFree(szValue);
  645. return(szItem);
  646. }
  647. DWORD
  648. RgszCount(
  649. RGSZ rgsz
  650. )
  651. /*
  652. Return the number of elements in an RGSZ
  653. */
  654. {
  655. DWORD i ;
  656. for ( i = 0 ; rgsz[i] ; i++ ) ;
  657. return i ;
  658. }
  659. SZ
  660. SzDup(
  661. SZ sz
  662. )
  663. {
  664. SZ NewSz = NULL;
  665. if ( sz ) {
  666. if ( (NewSz = (SZ)MyMalloc( strlen(sz) + 1 )) ) {
  667. strcpy( NewSz, sz );
  668. }
  669. }
  670. return NewSz;
  671. }
  672. //*************************************************************************
  673. //
  674. // RETURN BUFFER MANIPULATION
  675. //
  676. //*************************************************************************
  677. //
  678. // Return Text Routine
  679. //
  680. VOID
  681. SetReturnText(
  682. IN LPSTR Text
  683. )
  684. {
  685. lstrcpy( ReturnTextBuffer, Text );
  686. }
  687. VOID
  688. SetErrorText(
  689. IN DWORD ResID
  690. )
  691. {
  692. LoadString(ThisDLLHandle,(WORD)ResID,ReturnTextBuffer,sizeof(ReturnTextBuffer)-1);
  693. ReturnTextBuffer[sizeof(ReturnTextBuffer)-1] = '\0'; // just in case
  694. }
  695. //*************************************************************************
  696. //
  697. // FILE MANIPULATION
  698. //
  699. //*************************************************************************
  700. BOOL
  701. FFileFound(
  702. IN LPSTR szPath
  703. )
  704. {
  705. WIN32_FIND_DATA ffd;
  706. HANDLE SearchHandle;
  707. if ( (SearchHandle = FindFirstFile( szPath, &ffd )) == INVALID_HANDLE_VALUE ) {
  708. return( FALSE );
  709. }
  710. else {
  711. FindClose( SearchHandle );
  712. return( TRUE );
  713. }
  714. }
  715. BOOL
  716. FTransferSecurity(
  717. PCHAR Source,
  718. PCHAR Dest
  719. )
  720. {
  721. #define CBSDBUF 1024
  722. CHAR SdBuf[CBSDBUF];
  723. SECURITY_INFORMATION Si;
  724. PSECURITY_DESCRIPTOR Sd = (PSECURITY_DESCRIPTOR)SdBuf;
  725. DWORD cbSd = CBSDBUF;
  726. DWORD cbSdReq;
  727. PVOID AllocBuffer = NULL;
  728. BOOL Status;
  729. //
  730. // Get the security information from the source file
  731. //
  732. Si = OWNER_SECURITY_INFORMATION |
  733. GROUP_SECURITY_INFORMATION |
  734. DACL_SECURITY_INFORMATION;
  735. Status = GetFileSecurity(
  736. Source,
  737. Si,
  738. Sd,
  739. cbSd,
  740. &cbSdReq
  741. );
  742. if(!Status) {
  743. if( cbSdReq > CBSDBUF && (AllocBuffer = malloc( cbSdReq ))) {
  744. Sd = (PSECURITY_DESCRIPTOR)AllocBuffer;
  745. cbSd = cbSdReq;
  746. Status = GetFileSecurity(
  747. Source,
  748. Si,
  749. (PSECURITY_DESCRIPTOR)Sd,
  750. cbSd,
  751. &cbSdReq
  752. );
  753. }
  754. }
  755. if( !Status ) {
  756. return( FALSE );
  757. }
  758. //
  759. // Set the Security on the dest file
  760. //
  761. Status = SetFileSecurity(
  762. Dest,
  763. Si,
  764. Sd
  765. );
  766. if ( AllocBuffer ) {
  767. free( AllocBuffer );
  768. }
  769. return ( Status );
  770. }
  771. DWORD
  772. GetSizeOfFile(
  773. IN LPSTR szFile
  774. )
  775. {
  776. HANDLE hff;
  777. WIN32_FIND_DATA ffd;
  778. DWORD Size = 0;
  779. //
  780. // get find file information and get the size information out of
  781. // that
  782. //
  783. if ((hff = FindFirstFile(szFile, &ffd)) != INVALID_HANDLE_VALUE) {
  784. Size = ffd.nFileSizeLow;
  785. FindClose(hff);
  786. }
  787. return Size;
  788. }