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.

1685 lines
48 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. string.c
  5. Abstract:
  6. This file implements file functions for fax.
  7. Author:
  8. Wesley Witt (wesw) 23-Jan-1995
  9. Environment:
  10. User Mode
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <tchar.h>
  16. #include <Accctrl.h>
  17. #include <Aclapi.h>
  18. #include <Shellapi.h>
  19. #include <strsafe.h>
  20. #include "faxutil.h"
  21. #include "faxreg.h"
  22. #include "FaxUIConstants.h"
  23. VOID
  24. DeleteTempPreviewFiles (
  25. LPTSTR lptstrDirectory,
  26. BOOL bConsole
  27. )
  28. /*++
  29. Routine name : DeleteTempPreviewFiles
  30. Routine description:
  31. Deletes all the temporary fax preview TIFF files from a given folder.
  32. Deletes files: "<lptstrDirectory>\<PREVIEW_TIFF_PREFIX>*.<FAX_TIF_FILE_EXT>".
  33. Author:
  34. Eran Yariv (EranY), Apr, 2001
  35. Arguments:
  36. lptstrDirectory [in] - Folder.
  37. Optional - if NULL, the current user's temp dir is used.
  38. bConsole [in] - If TRUE, called from the client console. Otherwise, from the Fax Send Wizard.
  39. Return Value:
  40. None.
  41. --*/
  42. {
  43. TCHAR szTempPath[MAX_PATH * 2];
  44. TCHAR szSearch [MAX_PATH * 3];
  45. WIN32_FIND_DATA W32FindData;
  46. HANDLE hFind = INVALID_HANDLE_VALUE;
  47. TCHAR* pLast = NULL;
  48. HRESULT hRes;
  49. DEBUG_FUNCTION_NAME(TEXT("DeleteTempPreviewFiles"));
  50. if (!lptstrDirectory)
  51. {
  52. if (!GetTempPath( ARR_SIZE(szTempPath), szTempPath ))
  53. {
  54. DebugPrintEx(DEBUG_ERR,
  55. TEXT("GetTempPath() failed. (ec = %lu)"),
  56. GetLastError());
  57. return;
  58. }
  59. lptstrDirectory = szTempPath;
  60. }
  61. //
  62. // find last \ in path
  63. //
  64. pLast = _tcsrchr(lptstrDirectory,TEXT('\\'));
  65. if(pLast && (*_tcsinc(pLast)) == '\0')
  66. {
  67. //
  68. // the last character is a backslash, truncate it...
  69. //
  70. _tcsnset(pLast,'\0',1);
  71. }
  72. hRes = StringCchPrintf(
  73. szSearch,
  74. ARR_SIZE(szSearch),
  75. TEXT("%s\\%s%08x*.%s"),
  76. lptstrDirectory,
  77. bConsole ? CONSOLE_PREVIEW_TIFF_PREFIX : WIZARD_PREVIEW_TIFF_PREFIX,
  78. GetCurrentProcessId(),
  79. FAX_TIF_FILE_EXT
  80. );
  81. if (FAILED(hRes))
  82. {
  83. DebugPrintEx(DEBUG_ERR,
  84. TEXT("StringCchPrintf failed (ec=%lu)"),
  85. HRESULT_CODE(hRes));
  86. return;
  87. }
  88. hFind = FindFirstFile (szSearch, &W32FindData);
  89. if (INVALID_HANDLE_VALUE == hFind)
  90. {
  91. DebugPrintEx(DEBUG_ERR, TEXT("FindFirstFile failed with %ld"), GetLastError ());
  92. return;
  93. }
  94. //
  95. // Loop and delete all preview files
  96. //
  97. for (;;)
  98. {
  99. TCHAR szFile[MAX_PATH * 3];
  100. //
  101. // Compose full path to file
  102. //
  103. hRes = StringCchPrintf(
  104. szFile,
  105. ARR_SIZE(szFile),
  106. TEXT("%s\\%s"),
  107. lptstrDirectory,
  108. W32FindData.cFileName
  109. );
  110. if ( SUCCEEDED(hRes) )
  111. {
  112. //
  113. // Delete the currently found file
  114. //
  115. if (!DeleteFile (szFile))
  116. {
  117. DebugPrintEx(DEBUG_ERR, TEXT("DeleteFile(%s) failed with %ld"), szFile, GetLastError ());
  118. }
  119. else
  120. {
  121. DebugPrintEx(DEBUG_MSG, TEXT("%s deleted"), szFile);
  122. }
  123. }
  124. //
  125. // Find next file
  126. //
  127. if(!FindNextFile(hFind, &W32FindData))
  128. {
  129. if(ERROR_NO_MORE_FILES != GetLastError ())
  130. {
  131. DebugPrintEx(DEBUG_ERR, TEXT("FindNextFile failed with %ld"), GetLastError ());
  132. }
  133. else
  134. {
  135. //
  136. // End of files - no error
  137. //
  138. }
  139. break;
  140. }
  141. }
  142. FindClose (hFind);
  143. } // DeleteTempPreviewFiles
  144. DWORDLONG
  145. GenerateUniqueFileNameWithPrefix(
  146. BOOL bUseProcessId,
  147. LPTSTR lptstrDirectory,
  148. LPTSTR lptstrPrefix,
  149. LPTSTR lptstrExtension,
  150. LPTSTR lptstrFileName,
  151. DWORD dwFileNameSize
  152. )
  153. /*++
  154. Routine name : GenerateUniqueFileNameWithPrefix
  155. Routine description:
  156. Generates a unique file name
  157. Author:
  158. Eran Yariv (EranY), Apr, 2001
  159. Arguments:
  160. bUseProcessId [in] - If TRUE, the process id is appended after the prefix
  161. lptstrDirectory [in] - Directory where file should be created.
  162. Optional - if NULL, the current user's temp dir is used.
  163. lptstrPrefix [in] - File prefix.
  164. Optional - if NULL, no prefix is used.
  165. lptstrExtension [in] - File extension.
  166. Optional - if NULL, FAX_TIF_FILE_EXT is used.
  167. lptstrFileName [out] - File name.
  168. dwFileNameSize [in] - Size of file name (in characters)
  169. Return Value:
  170. Unique file identifier.
  171. Returns 0 in case of error (sets last error).
  172. --*/
  173. {
  174. DWORD i;
  175. TCHAR szTempPath[MAX_PATH * 2];
  176. TCHAR szProcessId[20] = {0};
  177. DWORDLONG dwlUniqueId = 0;
  178. HRESULT hRes;
  179. DEBUG_FUNCTION_NAME(TEXT("GenerateUniqueFileNameWithPrefix"));
  180. if (!lptstrDirectory)
  181. {
  182. if (!GetTempPath( ARR_SIZE(szTempPath), szTempPath ))
  183. {
  184. DebugPrintEx(DEBUG_ERR,
  185. TEXT("GetTempPath() failed. (ec = %lu)"),
  186. GetLastError());
  187. return 0;
  188. }
  189. lptstrDirectory = szTempPath;
  190. }
  191. TCHAR* pLast = NULL;
  192. pLast = _tcsrchr(lptstrDirectory,TEXT('\\'));
  193. if(pLast && (*_tcsinc(pLast)) == '\0')
  194. {
  195. //
  196. // the last character is a backslash, truncate it...
  197. //
  198. _tcsnset(pLast,'\0',1);
  199. }
  200. if (!lptstrExtension)
  201. {
  202. lptstrExtension = FAX_TIF_FILE_EXT;
  203. }
  204. if (!lptstrPrefix)
  205. {
  206. lptstrPrefix = TEXT("");
  207. }
  208. if (bUseProcessId)
  209. {
  210. hRes = StringCchPrintf (szProcessId, ARR_SIZE(szProcessId), TEXT("%08x"), GetCurrentProcessId());
  211. if (FAILED(hRes))
  212. {
  213. DebugPrintEx(DEBUG_ERR,
  214. TEXT("StringCchPrintf failed (ec=%lu)"),
  215. HRESULT_CODE(hRes));
  216. SetLastError(HRESULT_CODE(hRes));
  217. return 0;
  218. }
  219. }
  220. for (i=0; i<256; i++)
  221. {
  222. HANDLE hFile = INVALID_HANDLE_VALUE;
  223. FILETIME FileTime;
  224. SYSTEMTIME SystemTime;
  225. GetSystemTime( &SystemTime ); // returns VOID
  226. if (!SystemTimeToFileTime( &SystemTime, &FileTime ))
  227. {
  228. DebugPrintEx(DEBUG_ERR, TEXT("SystemTimeToFileTime() failed (ec: %ld)"), GetLastError());
  229. return 0;
  230. }
  231. dwlUniqueId = MAKELONGLONG(FileTime.dwLowDateTime, FileTime.dwHighDateTime);
  232. //
  233. // dwlUniqueId holds the number of 100 nanosecond units since 1.1.1601.
  234. // This occuipies most of the 64 bits.We we need some space to add extra
  235. // information (job type for example) to the job id.
  236. // Thus we give up the precision (1/10000000 of a second is too much for us anyhow)
  237. // to free up 8 MSB bits.
  238. // We shift right the time 8 bits to the right. This divides it by 256 which gives
  239. // us time resolution better than 1/10000 of a sec which is more than enough.
  240. //
  241. dwlUniqueId = dwlUniqueId >> 8;
  242. hRes = StringCchPrintf(
  243. lptstrFileName,
  244. dwFileNameSize,
  245. TEXT("%s\\%s%s%I64X.%s"),
  246. lptstrDirectory,
  247. lptstrPrefix,
  248. szProcessId,
  249. dwlUniqueId,
  250. lptstrExtension );
  251. if (FAILED(hRes))
  252. {
  253. DebugPrintEx(DEBUG_ERR,
  254. TEXT("StringCchPrintf failed (ec=%lu)"),
  255. HRESULT_CODE(hRes));
  256. SetLastError(HRESULT_CODE(hRes));
  257. return 0;
  258. }
  259. hFile = SafeCreateFile(
  260. lptstrFileName,
  261. GENERIC_WRITE,
  262. 0,
  263. NULL,
  264. CREATE_NEW,
  265. FILE_ATTRIBUTE_NORMAL,
  266. NULL);
  267. if (hFile == INVALID_HANDLE_VALUE)
  268. {
  269. DWORD dwError = GetLastError();
  270. if (dwError == ERROR_ALREADY_EXISTS || dwError == ERROR_FILE_EXISTS)
  271. {
  272. continue;
  273. }
  274. else
  275. {
  276. //
  277. // Real error
  278. //
  279. DebugPrintEx(DEBUG_ERR,
  280. TEXT("CreateFile() for [%s] failed. (ec: %ld)"),
  281. lptstrFileName,
  282. GetLastError());
  283. return 0;
  284. }
  285. }
  286. else
  287. {
  288. //
  289. // Success
  290. //
  291. CloseHandle (hFile);
  292. break;
  293. }
  294. }
  295. if (i == 256)
  296. {
  297. DebugPrintEx( DEBUG_ERR,
  298. TEXT("Failed to generate a unique file name after %d attempts. \n")
  299. TEXT("Last attempted UniqueIdValue value is: 0x%I64X \n")
  300. TEXT("Last attempted file name is : [%s]"),
  301. i,
  302. dwlUniqueId,
  303. lptstrFileName);
  304. SetLastError( ERROR_TOO_MANY_OPEN_FILES );
  305. return 0;
  306. }
  307. return dwlUniqueId;
  308. } // GenerateUniqueFileNameWithPrefix
  309. //*********************************************************************************
  310. //* Name: GenerateUniqueFileName()
  311. //* Author:
  312. //* Date:
  313. //*********************************************************************************
  314. //* DESCRIPTION:
  315. //* Generates a unique file in the queue directory.
  316. //* returns a UNIQUE id for the file.
  317. //* PARAMETERS:
  318. //* [IN] LPTSTR Directory
  319. //* The path where the file is to be created.
  320. //* [OUT] LPTSTR Extension
  321. //* The file extension that the generated file should have.
  322. //* [IN] LPTSTR FileName
  323. //* The buffer where the resulting file name (including path) will be
  324. //* placed, must be MAX_PATH.
  325. //* [IN] DWORD FileNameSize
  326. //* The size of the file name buffer.
  327. //* RETURN VALUE:
  328. //* If successful the function returns A DWORDLONG with the unique id for the file.
  329. //* On failure it returns 0.
  330. //* REMARKS:
  331. //* The generated unique id the 64 bit value of the system time.
  332. //* The generated file name is a string containing the hex representation of
  333. //* the 64 bit system time value.
  334. //*********************************************************************************
  335. DWORDLONG
  336. GenerateUniqueFileName(
  337. LPTSTR Directory,
  338. LPTSTR Extension,
  339. LPTSTR FileName,
  340. DWORD FileNameSize
  341. )
  342. {
  343. return GenerateUniqueFileNameWithPrefix (FALSE, Directory, NULL, Extension, FileName, FileNameSize);
  344. } // GenerateUniqueFileName
  345. BOOL
  346. MapFileOpen(
  347. LPCTSTR FileName,
  348. BOOL ReadOnly,
  349. DWORD ExtendBytes,
  350. PFILE_MAPPING FileMapping
  351. )
  352. {
  353. FileMapping->hFile = NULL;
  354. FileMapping->hMap = NULL;
  355. FileMapping->fPtr = NULL;
  356. FileMapping->hFile = SafeCreateFile(
  357. FileName,
  358. ReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
  359. ReadOnly ? FILE_SHARE_READ : 0,
  360. NULL,
  361. OPEN_EXISTING,
  362. 0,
  363. NULL);
  364. if (FileMapping->hFile == INVALID_HANDLE_VALUE)
  365. {
  366. return FALSE;
  367. }
  368. FileMapping->fSize = GetFileSize( FileMapping->hFile, NULL );
  369. FileMapping->hMap = CreateFileMapping(
  370. FileMapping->hFile,
  371. NULL,
  372. ReadOnly ? PAGE_READONLY : PAGE_READWRITE,
  373. 0,
  374. FileMapping->fSize + ExtendBytes,
  375. NULL
  376. );
  377. if (FileMapping->hMap == NULL)
  378. {
  379. CloseHandle( FileMapping->hFile );
  380. return FALSE;
  381. }
  382. FileMapping->fPtr = (LPBYTE)MapViewOfFileEx(
  383. FileMapping->hMap,
  384. ReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE,
  385. 0,
  386. 0,
  387. 0,
  388. NULL
  389. );
  390. if (FileMapping->fPtr == NULL)
  391. {
  392. CloseHandle( FileMapping->hFile );
  393. CloseHandle( FileMapping->hMap );
  394. return FALSE;
  395. }
  396. return TRUE;
  397. }
  398. VOID
  399. MapFileClose(
  400. PFILE_MAPPING FileMapping,
  401. DWORD TrimOffset
  402. )
  403. {
  404. UnmapViewOfFile( FileMapping->fPtr );
  405. CloseHandle( FileMapping->hMap );
  406. if (TrimOffset) {
  407. SetFilePointer( FileMapping->hFile, TrimOffset, NULL, FILE_BEGIN );
  408. SetEndOfFile( FileMapping->hFile );
  409. }
  410. CloseHandle( FileMapping->hFile );
  411. }
  412. //
  413. // Function: MultiFileCopy
  414. // Description: Copies multiple files from one directory to another.
  415. // In case of failure, return FALSE without any clean-up.
  416. // Validate that the path names and file names are not sum to be larger than MAX_PATH
  417. // Args:
  418. //
  419. // dwNumberOfFiles : Number of file names to copy
  420. // fileList : Array of strings: file names
  421. // lpctstrSrcDirectory : Source directory (with or without '\' at the end
  422. // lpctstrDestDirectory: Destination directory (with or without '\' at the end
  423. //
  424. // Author: AsafS
  425. BOOL
  426. MultiFileCopy(
  427. DWORD dwNumberOfFiles,
  428. LPCTSTR* fileList,
  429. LPCTSTR lpctstrSrcDirectory,
  430. LPCTSTR lpctstrDestDirerctory
  431. )
  432. {
  433. DEBUG_FUNCTION_NAME(TEXT("MultiFileCopy"))
  434. TCHAR szSrcPath [MAX_PATH];
  435. TCHAR szDestPath[MAX_PATH];
  436. HRESULT hRes;
  437. DWORD dwLengthOfDestDirectory = _tcslen(lpctstrDestDirerctory);
  438. DWORD dwLengthOfSrcDirectory = _tcslen(lpctstrSrcDirectory);
  439. // Make sure that all the file name lengths are not too big
  440. DWORD dwMaxPathLen = 1 + max((dwLengthOfDestDirectory),(dwLengthOfSrcDirectory));
  441. DWORD dwBufferLen = (sizeof(szSrcPath)/sizeof(TCHAR)) - 1;
  442. DWORD i=0;
  443. Assert (dwNumberOfFiles);
  444. for (i=0 ; i < dwNumberOfFiles ; i++)
  445. {
  446. if ( (_tcslen(fileList[i]) + dwMaxPathLen) > dwBufferLen )
  447. {
  448. DebugPrintEx(
  449. DEBUG_ERR,
  450. TEXT("The file/path names are too long")
  451. );
  452. SetLastError( ERROR_BUFFER_OVERFLOW );
  453. return (FALSE);
  454. }
  455. }
  456. hRes = StringCchCopy( szSrcPath,
  457. ARR_SIZE(szSrcPath),
  458. lpctstrSrcDirectory);
  459. if (FAILED(hRes))
  460. {
  461. DebugPrintEx(DEBUG_ERR,
  462. TEXT("StringCchCopy failed (ec=%lu)"),
  463. HRESULT_CODE(hRes));
  464. SetLastError( HRESULT_CODE(hRes) );
  465. return (FALSE);
  466. }
  467. hRes = StringCchCopy( szDestPath,
  468. ARR_SIZE(szDestPath),
  469. lpctstrDestDirerctory);
  470. if (FAILED(hRes))
  471. {
  472. DebugPrintEx(DEBUG_ERR,
  473. TEXT("StringCchCopy failed (ec=%lu)"),
  474. HRESULT_CODE(hRes));
  475. SetLastError( HRESULT_CODE(hRes) );
  476. return (FALSE);
  477. }
  478. //
  479. // Verify that directories end with '\\'.
  480. //
  481. TCHAR* pLast = NULL;
  482. pLast = _tcsrchr(szSrcPath,TEXT('\\'));
  483. if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
  484. {
  485. // the last character is not a backslash, add one...
  486. hRes = StringCchCat(szSrcPath, ARR_SIZE(szSrcPath), TEXT("\\"));
  487. if (FAILED(hRes))
  488. {
  489. DebugPrintEx(DEBUG_ERR,
  490. TEXT("StringCchCat failed (ec=%lu)"),
  491. HRESULT_CODE(hRes));
  492. SetLastError( HRESULT_CODE(hRes) );
  493. return (FALSE);
  494. }
  495. }
  496. pLast = _tcsrchr(szDestPath,TEXT('\\'));
  497. if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
  498. {
  499. // the last character is not a backslash, add one...
  500. hRes = StringCchCat(szDestPath, ARR_SIZE(szDestPath), TEXT("\\"));
  501. if (FAILED(hRes))
  502. {
  503. DebugPrintEx(DEBUG_ERR,
  504. TEXT("StringCchCat failed (ec=%lu)"),
  505. HRESULT_CODE(hRes));
  506. SetLastError( HRESULT_CODE(hRes) );
  507. return (FALSE);
  508. }
  509. }
  510. // Do the copy now
  511. for (i=0 ; i < dwNumberOfFiles ; i++)
  512. {
  513. TCHAR szSrcFile[MAX_PATH];
  514. TCHAR szDestFile[MAX_PATH];
  515. hRes = StringCchPrintf(
  516. szSrcFile,
  517. ARR_SIZE(szSrcFile),
  518. TEXT("%s%s"),
  519. szSrcPath,
  520. fileList[i]
  521. );
  522. if (FAILED(hRes))
  523. {
  524. DebugPrintEx(DEBUG_ERR,
  525. TEXT("StringCchPrintf failed (ec=%lu)"),
  526. HRESULT_CODE(hRes));
  527. SetLastError(HRESULT_CODE(hRes));
  528. return FALSE;
  529. }
  530. hRes = StringCchPrintf(
  531. szDestFile,
  532. ARR_SIZE(szDestFile),
  533. TEXT("%s%s"),
  534. szDestPath,
  535. fileList[i]
  536. );
  537. if (FAILED(hRes))
  538. {
  539. DebugPrintEx(DEBUG_ERR,
  540. TEXT("StringCchPrintf failed (ec=%lu)"),
  541. HRESULT_CODE(hRes));
  542. SetLastError(HRESULT_CODE(hRes));
  543. return FALSE;
  544. }
  545. if (!CopyFile(szSrcFile, szDestFile, FALSE))
  546. {
  547. DebugPrintEx(
  548. DEBUG_ERR,
  549. TEXT("CopyFile(%s, %s) failed: %d."),
  550. szSrcFile,
  551. szDestFile,
  552. GetLastError()
  553. );
  554. return(FALSE);
  555. }
  556. DebugPrintEx(
  557. DEBUG_MSG,
  558. TEXT("CopyFile(%s, %s) succeeded."),
  559. szSrcFile,
  560. szDestFile
  561. );
  562. }
  563. return TRUE;
  564. }
  565. //
  566. // Function: MultiFileDelete
  567. // Description: Deletes multiple files from given directory.
  568. // In case of failure, continue with the rest of the files and returns FALSE. Call to
  569. // GetLastError() to get the reason for the last failure that occured
  570. // If all DeleteFile calls were successful - return TRUE
  571. // Validate that the path name and file names are not sum to be larger than MAX_PATH
  572. // Args:
  573. //
  574. // dwNumberOfFiles : Number of file names to copy
  575. // fileList : Array of strings: file names
  576. // lpctstrFilesDirectory : Directory of the files (with or without '\' at the end
  577. //
  578. // Author: AsafS
  579. BOOL
  580. MultiFileDelete(
  581. DWORD dwNumberOfFiles,
  582. LPCTSTR* fileList,
  583. LPCTSTR lpctstrFilesDirectory
  584. )
  585. {
  586. DEBUG_FUNCTION_NAME(TEXT("MultiFileDelete"))
  587. BOOL retVal = TRUE;
  588. DWORD dwLastError = 0;
  589. TCHAR szFullPath[MAX_PATH];
  590. HRESULT hRes;
  591. DWORD dwLengthOfDirectoryName = _tcslen(lpctstrFilesDirectory);
  592. // Make sure that all the file name lengths are not too big
  593. DWORD dwBufferLen = (sizeof(szFullPath)/sizeof(TCHAR)) - 1;
  594. DWORD i;
  595. Assert (dwNumberOfFiles);
  596. for (i=0 ; i < dwNumberOfFiles ; i++)
  597. {
  598. if ( (_tcslen(fileList[i]) + dwLengthOfDirectoryName + 1) > dwBufferLen )
  599. {
  600. DebugPrintEx(
  601. DEBUG_ERR,
  602. TEXT("The file/path names are too long")
  603. );
  604. SetLastError( ERROR_BUFFER_OVERFLOW );
  605. return (FALSE);
  606. }
  607. }
  608. hRes = StringCchCopy(szFullPath ,ARR_SIZE(szFullPath), lpctstrFilesDirectory);
  609. if (FAILED(hRes))
  610. {
  611. DebugPrintEx(DEBUG_ERR,
  612. TEXT("StringCchCopy failed (ec=%lu)"),
  613. HRESULT_CODE(hRes));
  614. SetLastError( HRESULT_CODE(hRes) );
  615. return (FALSE);
  616. }
  617. dwLengthOfDirectoryName = _tcslen(lpctstrFilesDirectory);
  618. //
  619. // Verify that directory end with '\\' to the end of the path.
  620. //
  621. TCHAR* pLast = NULL;
  622. pLast = _tcsrchr(szFullPath,TEXT('\\'));
  623. if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
  624. {
  625. // the last character is not a backslash, add one...
  626. hRes = StringCchCat(szFullPath, ARR_SIZE(szFullPath), TEXT("\\"));
  627. if (FAILED(hRes))
  628. {
  629. DebugPrintEx(DEBUG_ERR,
  630. TEXT("StringCchCat failed (ec=%lu)"),
  631. HRESULT_CODE(hRes));
  632. SetLastError( HRESULT_CODE(hRes) );
  633. return (FALSE);
  634. }
  635. }
  636. for(i=0 ; i < dwNumberOfFiles ; i++)
  637. {
  638. TCHAR szFileName[MAX_PATH];
  639. hRes = StringCchPrintf(
  640. szFileName,
  641. ARR_SIZE(szFileName),
  642. TEXT("%s%s"),
  643. szFullPath,
  644. fileList[i]
  645. );
  646. if (FAILED(hRes))
  647. {
  648. DebugPrintEx(DEBUG_ERR,
  649. TEXT("StringCchPrintf failed (ec=%lu)"),
  650. HRESULT_CODE(hRes));
  651. SetLastError(HRESULT_CODE(hRes));
  652. return FALSE;
  653. }
  654. if (!DeleteFile(szFileName))
  655. {
  656. dwLastError = GetLastError();
  657. DebugPrintEx(
  658. DEBUG_ERR,
  659. TEXT("Delete (%s) failed: %d."),
  660. szFileName,
  661. dwLastError
  662. );
  663. retVal = FALSE; // Continue with the list
  664. }
  665. else
  666. {
  667. DebugPrintEx(
  668. DEBUG_MSG,
  669. TEXT("Delete (%s) succeeded."),
  670. szFileName
  671. );
  672. }
  673. }
  674. if (!retVal) // In case there was a failure to delete any file
  675. {
  676. SetLastError(dwLastError);
  677. DebugPrintEx(
  678. DEBUG_ERR,
  679. TEXT("Delete files from (%s) failed: %d."),
  680. szFullPath,
  681. dwLastError
  682. );
  683. }
  684. return retVal;
  685. }
  686. BOOL
  687. ValidateCoverpage(
  688. IN LPCTSTR CoverPageName,
  689. IN LPCTSTR ServerName,
  690. IN BOOL ServerCoverpage,
  691. OUT LPTSTR ResolvedName,
  692. IN DWORD dwResolvedNameSize
  693. )
  694. /*++
  695. Routine Description:
  696. This routine tries to validate that that coverpage specified by the user actually exists where
  697. they say it does, and that it is indeed a coverpage (or a resolvable link to one)
  698. Please see the SDK for documentation on the rules for how server coverpages work, etc.
  699. Arguments:
  700. CoverpageName - contains name of coverpage
  701. ServerName - name of the server, if any (can be null)
  702. ServerCoverpage - indicates if this coverpage is on the server, or in the server location for
  703. coverpages locally
  704. ResolvedName - a pointer to buffer (should be MAX_PATH large at least) to receive the
  705. resolved coverpage name.
  706. dwResolvedNameSize - holds the size of ResolvedName buffer in TCAHRs
  707. Return Value:
  708. TRUE if coverpage can be used.
  709. FALSE if the coverpage is invalid or cannot be used.
  710. --*/
  711. {
  712. LPTSTR p;
  713. DWORD ec = ERROR_SUCCESS;
  714. TCHAR CpDir [MAX_PATH];
  715. TCHAR tszExt[_MAX_EXT];
  716. TCHAR tszFileName[_MAX_FNAME];
  717. HRESULT hRes;
  718. DEBUG_FUNCTION_NAME(TEXT("ValidateCoverpage"));
  719. Assert (ResolvedName);
  720. if (!CoverPageName)
  721. {
  722. ec = ERROR_INVALID_PARAMETER;
  723. goto exit;
  724. }
  725. hRes = StringCchCopy(CpDir, ARR_SIZE(CpDir), CoverPageName);
  726. if (FAILED(hRes))
  727. {
  728. DebugPrintEx(DEBUG_ERR,
  729. TEXT("StringCchCopy failed (ec=%lu)"),
  730. HRESULT_CODE(hRes));
  731. ec = HRESULT_CODE(hRes);
  732. goto exit;
  733. }
  734. if (TRUE == ServerCoverpage)
  735. {
  736. //
  737. // If this is a server cover page, make sure we only have the file name
  738. //
  739. TCHAR tszFullFileName[MAX_PATH];
  740. _tsplitpath(CpDir, NULL, NULL, tszFileName, tszExt);
  741. hRes = StringCchCopy(tszFullFileName, ARR_SIZE(tszFullFileName), tszFileName);
  742. if (FAILED(hRes))
  743. {
  744. //
  745. // Can not happen. CpDir is MAX_PATH
  746. //
  747. Assert (FALSE);
  748. }
  749. hRes = StringCchCat(tszFullFileName, ARR_SIZE(tszFullFileName), tszExt);
  750. if (FAILED(hRes))
  751. {
  752. //
  753. // Can not happen. CpDir is MAX_PATH
  754. //
  755. Assert (FALSE);
  756. }
  757. if (0 != _tcsicmp(tszFullFileName, CpDir))
  758. {
  759. DebugPrintEx(
  760. DEBUG_ERR,
  761. TEXT("server coverpage does not contain file name only. cover page name: %s "),
  762. CpDir);
  763. ec = ERROR_INVALID_PARAMETER;
  764. goto exit;
  765. }
  766. if (0 == _tcsicmp(tszExt, CP_SHORTCUT_EXT) )
  767. {
  768. DebugPrintEx(DEBUG_ERR,
  769. _T("Server Based Cover Page File Name should not be a link : %s"),
  770. CpDir);
  771. ec = ERROR_INVALID_PARAMETER;
  772. goto exit;
  773. }
  774. }
  775. p = _tcschr(CpDir, FAX_PATH_SEPARATOR_CHR );
  776. if (p)
  777. {
  778. //
  779. // the coverpage file name contains a path so just use it.
  780. //
  781. if (GetFileAttributes( CpDir ) == 0xffffffff)
  782. {
  783. ec = ERROR_FILE_NOT_FOUND;
  784. DebugPrintEx(DEBUG_ERR,
  785. _T("GetFileAttributes failed for %ws. ec = %ld"),
  786. CpDir,
  787. ec);
  788. goto exit;
  789. }
  790. }
  791. else
  792. {
  793. //
  794. // the coverpage file name does not contain
  795. // a path so we must construct a full path name
  796. //
  797. if (ServerCoverpage)
  798. {
  799. if (!ServerName || ServerName[0] == 0)
  800. {
  801. if (!GetServerCpDir( NULL, CpDir, sizeof(CpDir) / sizeof(CpDir[0]) ))
  802. {
  803. ec = GetLastError ();
  804. DebugPrintEx(DEBUG_ERR,
  805. _T("GetServerCpDir failed . ec = %ld"),
  806. GetLastError());
  807. }
  808. }
  809. else
  810. {
  811. if (!GetServerCpDir( ServerName, CpDir, sizeof(CpDir) / sizeof(CpDir[0]) ))
  812. {
  813. ec = GetLastError ();
  814. DebugPrintEx(DEBUG_ERR,
  815. _T("GetServerCpDir failed . ec = %ld"),
  816. GetLastError());
  817. }
  818. }
  819. }
  820. else
  821. {
  822. if (!GetClientCpDir( CpDir, sizeof(CpDir) / sizeof(CpDir[0])))
  823. {
  824. ec = GetLastError ();
  825. DebugPrintEx(DEBUG_ERR,
  826. _T("GetClientCpDir failed . ec = %ld"),
  827. GetLastError());
  828. }
  829. }
  830. if (ERROR_SUCCESS != ec)
  831. {
  832. ec = ERROR_FILE_NOT_FOUND;
  833. goto exit;
  834. }
  835. hRes = StringCchCat( CpDir, ARR_SIZE(CpDir), TEXT("\\") );
  836. if (FAILED(hRes))
  837. {
  838. DebugPrintEx(DEBUG_ERR,
  839. TEXT("StringCchCat failed (ec=%lu)"),
  840. HRESULT_CODE(hRes));
  841. ec = HRESULT_CODE(hRes);
  842. goto exit;
  843. }
  844. hRes = StringCchCat( CpDir, ARR_SIZE(CpDir), CoverPageName );
  845. if (FAILED(hRes))
  846. {
  847. DebugPrintEx(DEBUG_ERR,
  848. TEXT("StringCchCat failed (ec=%lu)"),
  849. HRESULT_CODE(hRes));
  850. ec = HRESULT_CODE(hRes);
  851. goto exit;
  852. }
  853. _tsplitpath(CpDir, NULL, NULL, NULL, tszExt);
  854. if (!_tcslen(tszExt))
  855. {
  856. hRes = StringCchCat( CpDir, ARR_SIZE(CpDir), FAX_COVER_PAGE_FILENAME_EXT );
  857. if (FAILED(hRes))
  858. {
  859. DebugPrintEx(DEBUG_ERR,
  860. TEXT("StringCchCat failed (ec=%lu)"),
  861. HRESULT_CODE(hRes));
  862. ec = HRESULT_CODE(hRes);
  863. goto exit;
  864. }
  865. }
  866. if (GetFileAttributes( CpDir ) == 0xffffffff)
  867. {
  868. ec = ERROR_FILE_NOT_FOUND;
  869. goto exit;
  870. }
  871. }
  872. hRes = StringCchCopy( ResolvedName, dwResolvedNameSize, CpDir );
  873. if (FAILED(hRes))
  874. {
  875. DebugPrintEx(DEBUG_ERR,
  876. TEXT("StringCchCopy failed (ec=%lu)"),
  877. HRESULT_CODE(hRes));
  878. ec = HRESULT_CODE(hRes);
  879. goto exit;
  880. }
  881. //
  882. // Make sure it is not a device
  883. // Try to open file
  884. //
  885. HANDLE hFile = SafeCreateFile (
  886. ResolvedName,
  887. GENERIC_READ,
  888. FILE_SHARE_READ,
  889. NULL,
  890. OPEN_EXISTING,
  891. FILE_ATTRIBUTE_NORMAL,
  892. NULL);
  893. if ( INVALID_HANDLE_VALUE == hFile )
  894. {
  895. ec = GetLastError ();
  896. DebugPrintEx(
  897. DEBUG_ERR,
  898. TEXT("Opening %s for read failed (ec: %ld)"),
  899. ResolvedName,
  900. ec);
  901. goto exit;
  902. }
  903. if (!CloseHandle (hFile))
  904. {
  905. DebugPrintEx(
  906. DEBUG_ERR,
  907. TEXT("CloseHandle failed (ec: %ld)"),
  908. GetLastError());
  909. }
  910. Assert (ERROR_SUCCESS == ec);
  911. exit:
  912. if (ERROR_SUCCESS != ec)
  913. {
  914. SetLastError(ec);
  915. return FALSE;
  916. }
  917. return TRUE;
  918. } // ValidateCoverpage
  919. DWORD
  920. ViewFile (
  921. LPCTSTR lpctstrFile
  922. )
  923. /*++
  924. Routine Description:
  925. Launches the application associated with a given file to view it.
  926. We first attempt to use the "open" verb.
  927. If that fails, we try the NULL (default) verb.
  928. Arguments:
  929. lpctstrFile [in] - File name
  930. Return Value:
  931. Standard Win32 error code
  932. --*/
  933. {
  934. DWORD dwRes = ERROR_SUCCESS;
  935. SHELLEXECUTEINFO executeInfo = {0};
  936. DEBUG_FUNCTION_NAME(TEXT("ViewFile"));
  937. executeInfo.cbSize = sizeof(executeInfo);
  938. executeInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_DDEWAIT;
  939. executeInfo.lpVerb = TEXT("open");
  940. executeInfo.lpFile = lpctstrFile;
  941. executeInfo.nShow = SW_SHOWNORMAL;
  942. //
  943. // Execute the associated application with the "open" verb
  944. //
  945. if(!ShellExecuteEx(&executeInfo))
  946. {
  947. DebugPrintEx(
  948. DEBUG_ERR,
  949. TEXT("ShellExecuteEx(open) failed (ec: %ld)"),
  950. GetLastError());
  951. //
  952. // "open" verb is not supported. Try the NULL (default) verb.
  953. //
  954. executeInfo.lpVerb = NULL;
  955. if(!ShellExecuteEx(&executeInfo))
  956. {
  957. dwRes = GetLastError();
  958. DebugPrintEx(
  959. DEBUG_ERR,
  960. TEXT("ShellExecuteEx(NULL) failed (ec: %ld)"),
  961. dwRes);
  962. }
  963. }
  964. return dwRes;
  965. } // ViewFile
  966. #ifdef UNICODE
  967. DWORD
  968. CheckToSeeIfSameDir(
  969. LPWSTR lpwstrDir1,
  970. LPWSTR lpwstrDir2,
  971. BOOL* pIsSameDir
  972. )
  973. {
  974. /*++
  975. Routine name : IsDiffrentDir
  976. Routine description:
  977. Checks if both paths point to the same directory. Note that the directory pointed by lpwstrDir1 must exist.
  978. Author:
  979. Oded Sacher (OdedS), Aug, 2000
  980. Arguments:
  981. lpwstrDir1 [in] - First path - the directory must exist.
  982. lpwstrDir2 [in] - Second path - the directory does not have to exist
  983. pIsSameDir [out] - Receives the answer to "IsSameDir?" Valid only if the function succeeds.
  984. Return Value:
  985. Win32 Erorr code
  986. --*/
  987. Assert (lpwstrDir1 && lpwstrDir2 && pIsSameDir);
  988. DWORD ec = ERROR_SUCCESS;
  989. WCHAR wszTestFile1[MAX_PATH];
  990. WCHAR wszTestFile2[MAX_PATH * 2];
  991. BOOL fFileCreated = FALSE;
  992. HANDLE hFile1 = INVALID_HANDLE_VALUE;
  993. HANDLE hFile2 = INVALID_HANDLE_VALUE;
  994. LPWSTR lpwstrFileName = NULL;
  995. DEBUG_FUNCTION_NAME(TEXT("CheckToSeeIfSameDir)"));
  996. HRESULT hRes;
  997. if (0 == _wcsicmp(lpwstrDir1, lpwstrDir2))
  998. {
  999. *pIsSameDir = TRUE;
  1000. return ERROR_SUCCESS;
  1001. }
  1002. //
  1003. // Create temporary files
  1004. //
  1005. if (!GetTempFileName (lpwstrDir1, L"TST", 0, wszTestFile1))
  1006. {
  1007. //
  1008. // Either the folder doesn't exist or we don't have access
  1009. //
  1010. ec = GetLastError ();
  1011. DebugPrintEx(
  1012. DEBUG_ERR,
  1013. TEXT("GetTempFileName failed with %ld"), ec);
  1014. goto exit;
  1015. }
  1016. //
  1017. // GetTempFileName created 0 bytes file, that we need to delete before exiting
  1018. //
  1019. fFileCreated = TRUE;
  1020. hFile1 = SafeCreateFile(
  1021. wszTestFile1,
  1022. 0,
  1023. FILE_SHARE_READ|FILE_SHARE_WRITE,
  1024. NULL,
  1025. OPEN_EXISTING,
  1026. 0,
  1027. NULL);
  1028. if (INVALID_HANDLE_VALUE == hFile1)
  1029. {
  1030. ec = GetLastError();
  1031. DebugPrintEx(DEBUG_ERR,
  1032. TEXT("CreateFile failed (ec: %ld)"),
  1033. ec);
  1034. goto exit;
  1035. }
  1036. lpwstrFileName = wcsrchr(wszTestFile1, L'\\');
  1037. Assert (lpwstrFileName);
  1038. hRes = StringCchCopy (wszTestFile2, ARR_SIZE(wszTestFile2), lpwstrDir2);
  1039. if (FAILED(hRes))
  1040. {
  1041. DebugPrintEx(DEBUG_ERR,
  1042. TEXT("StringCchCopy failed (ec=%lu)"),
  1043. HRESULT_CODE(hRes));
  1044. ec = HRESULT_CODE(hRes);
  1045. goto exit;
  1046. }
  1047. hRes = StringCchCat (wszTestFile2, ARR_SIZE(wszTestFile2), lpwstrFileName);
  1048. if (FAILED(hRes))
  1049. {
  1050. DebugPrintEx(DEBUG_ERR,
  1051. TEXT("StringCchCat failed (ec=%lu)"),
  1052. HRESULT_CODE(hRes));
  1053. ec = HRESULT_CODE(hRes);
  1054. goto exit;
  1055. }
  1056. hFile2 = SafeCreateFile(
  1057. wszTestFile2,
  1058. 0,
  1059. FILE_SHARE_READ|FILE_SHARE_WRITE,
  1060. NULL,
  1061. OPEN_EXISTING,
  1062. 0,
  1063. NULL);
  1064. if (INVALID_HANDLE_VALUE == hFile2)
  1065. {
  1066. //
  1067. // Check if failure is *NOT* because of access or availability
  1068. //
  1069. ec = GetLastError ();
  1070. if (ERROR_NOT_ENOUGH_MEMORY == ec ||
  1071. ERROR_OUTOFMEMORY == ec )
  1072. {
  1073. DebugPrintEx(DEBUG_ERR,
  1074. TEXT("CreateFile failed (ec: %ld)"),
  1075. ec);
  1076. goto exit;
  1077. }
  1078. //
  1079. // On any other failure we asssume that the paths are diffrent
  1080. //
  1081. *pIsSameDir = FALSE;
  1082. ec = ERROR_SUCCESS;
  1083. goto exit;
  1084. }
  1085. BY_HANDLE_FILE_INFORMATION hfi1;
  1086. BY_HANDLE_FILE_INFORMATION hfi2;
  1087. if (!GetFileInformationByHandle(hFile1, &hfi1))
  1088. {
  1089. ec = GetLastError();
  1090. DebugPrintEx(DEBUG_ERR,
  1091. TEXT("GetFileInformationByHandle failed (ec: %ld)"),
  1092. ec);
  1093. goto exit;
  1094. }
  1095. if (!GetFileInformationByHandle(hFile2, &hfi2))
  1096. {
  1097. ec = GetLastError();
  1098. DebugPrintEx(DEBUG_ERR,
  1099. TEXT("GetFileInformationByHandle failed (ec: %ld)"),
  1100. ec);
  1101. goto exit;
  1102. }
  1103. if ((hfi1.nFileIndexHigh == hfi2.nFileIndexHigh) &&
  1104. (hfi1.nFileIndexLow == hfi2.nFileIndexLow) &&
  1105. (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber))
  1106. {
  1107. *pIsSameDir = TRUE;
  1108. }
  1109. else
  1110. {
  1111. *pIsSameDir = FALSE;
  1112. }
  1113. Assert (ERROR_SUCCESS == ec);
  1114. exit:
  1115. if (INVALID_HANDLE_VALUE != hFile1)
  1116. {
  1117. if (!CloseHandle(hFile1))
  1118. {
  1119. DebugPrintEx(DEBUG_ERR,
  1120. TEXT("CloseHandle failed (ec: %ld)"),
  1121. GetLastError());
  1122. }
  1123. }
  1124. if (INVALID_HANDLE_VALUE != hFile2)
  1125. {
  1126. if (!CloseHandle(hFile2))
  1127. {
  1128. DebugPrintEx(DEBUG_ERR,
  1129. TEXT("CloseHandle failed (ec: %ld)"),
  1130. GetLastError());
  1131. }
  1132. }
  1133. if (TRUE == fFileCreated)
  1134. {
  1135. if (!DeleteFile(wszTestFile1))
  1136. {
  1137. DebugPrintEx(DEBUG_ERR,
  1138. TEXT("DeleteFile failed. File: %s, (ec: %ld)"),
  1139. wszTestFile1,
  1140. GetLastError());
  1141. }
  1142. }
  1143. return ec;
  1144. }
  1145. #endif //UNICODE
  1146. typedef enum
  1147. {
  1148. SAFE_METAFILE_SEMANTICS_NONE = 0x00000000,
  1149. SAFE_METAFILE_SEMANTICS_TEMP = 0x00000001, // File is temporary. Should be deleted on close / reboot
  1150. SAFE_METAFILE_SEMANTICS_SENSITIVE = 0x00000002 // File contains sensitive information. Should not be indexed
  1151. } SAFE_METAFILE_SEMANTICS;
  1152. static
  1153. HANDLE
  1154. InternalSafeCreateFile(
  1155. LPCTSTR IN lpFileName, // File name
  1156. DWORD IN dwDesiredAccess, // Access mode
  1157. DWORD IN dwShareMode, // Share mode
  1158. LPSECURITY_ATTRIBUTES IN lpSecurityAttributes, // SD
  1159. DWORD IN dwCreationDisposition, // How to create
  1160. DWORD IN dwFlagsAndAttributes, // File attributes
  1161. HANDLE IN hTemplateFile, // Handle to template file
  1162. DWORD IN dwMetaFileSemantics // Meta file semantics
  1163. )
  1164. /*++
  1165. Routine name : InternalSafeCreateFile
  1166. Routine description:
  1167. This is a safe wrapper around the Win32 CreateFile API.
  1168. It only supports creating real files (as opposed to COM ports, named pipes, etc.).
  1169. It uses some widely-discussed mitigation techniques to guard agaist some well known security
  1170. issues in CreateFile().
  1171. Author:
  1172. Eran Yariv (EranY), Mar, 2002
  1173. Arguments:
  1174. lpFileName [in] - Refer to the CreateFile() documentation for parameter description.
  1175. dwDesiredAccess [in] - Refer to the CreateFile() documentation for parameter description.
  1176. dwShareMode [in] - Refer to the CreateFile() documentation for parameter description.
  1177. lpSecurityAttributes [in] - Refer to the CreateFile() documentation for parameter description.
  1178. dwCreationDisposition [in] - Refer to the CreateFile() documentation for parameter description.
  1179. dwFlagsAndAttributes [in] - Refer to the CreateFile() documentation for parameter description.
  1180. hTemplateFile [in] - Refer to the CreateFile() documentation for parameter description.
  1181. dwMetaFileSemantics [in] - Meta file semantics.
  1182. This parameter can be a combination of the following values:
  1183. SAFE_METAFILE_SEMANTICS_TEMP
  1184. The file is a temporary file.
  1185. The file will be created / opened using the FILE_FLAG_DELETE_ON_CLOSE flag.
  1186. When the last file handle is closed, the file will be automatically deleted.
  1187. In addition, the file is marked for deletion after reboot (Unicode-version only).
  1188. This will only work if the calling thread's user is a member of the local admins group.
  1189. If marking for deletion-post-reboot fails, the InternalSafeCreateFile function call still succeeds.
  1190. SAFE_METAFILE_SEMANTICS_SENSITIVE
  1191. The file contains sensitive information.
  1192. The current implementation of this function will mark the file with the
  1193. FILE_ATTRIBUTE_NOT_CONTENT_INDEXED flag.
  1194. Return Value:
  1195. If the function succeeds, the return value is an open handle to the specified file.
  1196. If the specified file exists before the function call and dwCreationDisposition is CREATE_ALWAYS or OPEN_ALWAYS,
  1197. a call to GetLastError returns ERROR_ALREADY_EXISTS (even though the function has succeeded).
  1198. If the file does not exist before the call, GetLastError returns zero.
  1199. If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
  1200. For more information see the "Return value" section in the CreateFile() documentation.
  1201. Remarks:
  1202. Please refer to the CreateFile() documentation.
  1203. --*/
  1204. {
  1205. HANDLE hFile;
  1206. DWORD dwFaxFlagsAndAttributes = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS;
  1207. DWORD dwFaxShareMode = 0;
  1208. DEBUG_FUNCTION_NAME(TEXT("InternalSafeCreateFile"));
  1209. //
  1210. // Always use SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS in file flags and attributes.
  1211. // This prevents us from opening a user-supplied named pipe and allowing the other side
  1212. // of that pipe to impersonate the caller.
  1213. //
  1214. if (SAFE_METAFILE_SEMANTICS_SENSITIVE & dwMetaFileSemantics)
  1215. {
  1216. //
  1217. // File contains sensitive data. It should not be indexed.
  1218. //
  1219. dwFaxFlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
  1220. }
  1221. if (SAFE_METAFILE_SEMANTICS_TEMP & dwMetaFileSemantics)
  1222. {
  1223. //
  1224. // File is temporary.
  1225. //
  1226. dwFaxFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
  1227. #ifdef UNICODE
  1228. dwFaxShareMode = FILE_SHARE_DELETE;
  1229. #endif // UNICODE
  1230. }
  1231. hFile = CreateFile (lpFileName,
  1232. dwDesiredAccess,
  1233. dwShareMode | dwFaxShareMode,
  1234. lpSecurityAttributes,
  1235. dwCreationDisposition,
  1236. dwFlagsAndAttributes | dwFaxFlagsAndAttributes,
  1237. hTemplateFile);
  1238. if (INVALID_HANDLE_VALUE == hFile)
  1239. {
  1240. return hFile;
  1241. }
  1242. //
  1243. // Never allow using non-disk file (e.g. COM ports)
  1244. //
  1245. if (FILE_TYPE_DISK != GetFileType (hFile))
  1246. {
  1247. CloseHandle (hFile);
  1248. SetLastError (ERROR_UNSUPPORTED_TYPE);
  1249. return INVALID_HANDLE_VALUE;
  1250. }
  1251. #ifdef UNICODE
  1252. if (SAFE_METAFILE_SEMANTICS_TEMP & dwMetaFileSemantics)
  1253. {
  1254. //
  1255. // File is temporary.
  1256. // Mark it for delete after reboot.
  1257. // This can fail if we're not admins. That's why we're not checking return value from MoveFileEx.
  1258. //
  1259. MoveFileEx (lpFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  1260. }
  1261. #endif // UNICODE
  1262. return hFile;
  1263. } // InternalSafeCreateFile
  1264. HANDLE
  1265. SafeCreateFile(
  1266. LPCTSTR IN lpFileName, // File name
  1267. DWORD IN dwDesiredAccess, // Access mode
  1268. DWORD IN dwShareMode, // Share mode
  1269. LPSECURITY_ATTRIBUTES IN lpSecurityAttributes, // SD
  1270. DWORD IN dwCreationDisposition, // How to create
  1271. DWORD IN dwFlagsAndAttributes, // File attributes
  1272. HANDLE IN hTemplateFile // Handle to template file
  1273. )
  1274. {
  1275. return InternalSafeCreateFile (lpFileName,
  1276. dwDesiredAccess,
  1277. dwShareMode,
  1278. lpSecurityAttributes,
  1279. dwCreationDisposition,
  1280. dwFlagsAndAttributes,
  1281. hTemplateFile,
  1282. SAFE_METAFILE_SEMANTICS_SENSITIVE);
  1283. } // SafeCreateFile
  1284. HANDLE
  1285. SafeCreateTempFile(
  1286. LPCTSTR IN lpFileName, // File name
  1287. DWORD IN dwDesiredAccess, // Access mode
  1288. DWORD IN dwShareMode, // Share mode
  1289. LPSECURITY_ATTRIBUTES IN lpSecurityAttributes, // SD
  1290. DWORD IN dwCreationDisposition, // How to create
  1291. DWORD IN dwFlagsAndAttributes, // File attributes
  1292. HANDLE IN hTemplateFile // Handle to template file
  1293. )
  1294. {
  1295. return InternalSafeCreateFile (lpFileName,
  1296. dwDesiredAccess,
  1297. dwShareMode,
  1298. lpSecurityAttributes,
  1299. dwCreationDisposition,
  1300. dwFlagsAndAttributes,
  1301. hTemplateFile,
  1302. SAFE_METAFILE_SEMANTICS_SENSITIVE |
  1303. SAFE_METAFILE_SEMANTICS_TEMP);
  1304. } // SafeCreateTempFile
  1305. DWORD
  1306. IsValidFaxFolder(
  1307. LPCTSTR szFolder
  1308. )
  1309. /*++
  1310. Routine name : IsValidFaxFolder
  1311. Routine description:
  1312. Check if fax service has access right to a given folder.
  1313. The routine checks for these rights:
  1314. o Create file/Write file
  1315. o Enumerate files
  1316. o Delete file
  1317. Author:
  1318. Caliv Nir (t-nicali) Mar, 2002
  1319. Arguments:
  1320. lpwstrFolder [in] - the folder name.
  1321. Return Value:
  1322. Win32 error code. ERROR_SUCCESS if the folder can be used by fax service.
  1323. Otherwise, the Win32 error code to return to the caller.
  1324. --*/
  1325. {
  1326. TCHAR szTestFile[MAX_PATH]={0};
  1327. DWORD dwFileAtt;
  1328. LPTSTR szExpandedFolder = NULL;
  1329. HANDLE hFind = INVALID_HANDLE_VALUE;
  1330. WIN32_FIND_DATA FindFileData = {0};
  1331. BOOL bFileCreated = FALSE;
  1332. DWORD ec = ERROR_SUCCESS;
  1333. DEBUG_FUNCTION_NAME(TEXT("IsValidFaxFolder"));
  1334. szExpandedFolder = ExpandEnvironmentString( szFolder );
  1335. if (!szExpandedFolder)
  1336. {
  1337. ec = GetLastError();
  1338. DebugPrintEx( DEBUG_ERR,
  1339. TEXT("ExpandEnvironmentString failed (ec=%lu)."),
  1340. ec);
  1341. return ec;
  1342. }
  1343. //
  1344. // Check to see if the directory exist
  1345. //
  1346. dwFileAtt = GetFileAttributes( szExpandedFolder );
  1347. if (INVALID_FILE_ATTRIBUTES == dwFileAtt || !(dwFileAtt & FILE_ATTRIBUTE_DIRECTORY))
  1348. {
  1349. //
  1350. // The directory does not exists
  1351. //
  1352. ec = GetLastError ();
  1353. DebugPrintEx(
  1354. DEBUG_ERR,
  1355. TEXT("GetFileAttributes failed with %lu"), ec);
  1356. goto exit;
  1357. }
  1358. //
  1359. // Verify that we have access to this folder - Create a temporary file
  1360. //
  1361. if (!GetTempFileName (szExpandedFolder, TEXT("TST"), 0, szTestFile))
  1362. {
  1363. //
  1364. // Either the folder doesn't exist or we don't have access
  1365. //
  1366. ec = GetLastError ();
  1367. DebugPrintEx(
  1368. DEBUG_ERR,
  1369. TEXT("GetTempFileName failed with %ld"), ec);
  1370. goto exit;
  1371. }
  1372. bFileCreated = TRUE;
  1373. //
  1374. // Try to enumarate files in this folder
  1375. //
  1376. hFind = FindFirstFile(szTestFile, &FindFileData);
  1377. if (hFind == INVALID_HANDLE_VALUE)
  1378. {
  1379. //
  1380. // Couldn't enumerate folder
  1381. //
  1382. ec = GetLastError ();
  1383. DebugPrintEx(
  1384. DEBUG_ERR,
  1385. TEXT("FindFirstFile failed with %ld"), ec);
  1386. goto exit;
  1387. }
  1388. Assert(ec == ERROR_SUCCESS);
  1389. exit:
  1390. //
  1391. // Close find handle
  1392. //
  1393. if (hFind != INVALID_HANDLE_VALUE)
  1394. {
  1395. if(!FindClose(hFind))
  1396. {
  1397. DebugPrintEx(
  1398. DEBUG_ERR,
  1399. TEXT("FindClose failed with %ld"), GetLastError ());
  1400. }
  1401. }
  1402. if (bFileCreated)
  1403. {
  1404. //
  1405. // Delete the file
  1406. //
  1407. if (!DeleteFile(szTestFile))
  1408. {
  1409. /***********************************************************
  1410. /* Although it's a clean up code we propagate the error code
  1411. /* It may say that we lack the permission to delete this
  1412. /* file.
  1413. /***********************************************************/
  1414. ec = GetLastError ();
  1415. DebugPrintEx(
  1416. DEBUG_ERR,
  1417. TEXT("DeleteFile() failed with %ld"),ec);
  1418. }
  1419. }
  1420. MemFree(szExpandedFolder);
  1421. return ec;
  1422. } // IsValidFaxFolder