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.

340 lines
10 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: FLNFILE.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 10/13/1999
  12. *
  13. * DESCRIPTION: Find the lowest numbered files in a given directory with a given
  14. * root filename.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #include "flnfile.h"
  20. ///////////////////////////////
  21. // DoesFileExist
  22. //
  23. bool NumberedFileName::DoesFileExist(LPCTSTR pszFileName)
  24. {
  25. DWORD dwFileAttr = 0;
  26. DWORD dwError = 0;
  27. dwFileAttr = GetFileAttributes(pszFileName);
  28. if (dwFileAttr == 0xFFFFFFFF)
  29. {
  30. // file not found
  31. dwError = GetLastError();
  32. return false;
  33. }
  34. if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY)
  35. {
  36. //
  37. // file name is a directory
  38. //
  39. return false;
  40. }
  41. return true;
  42. }
  43. ///////////////////////////////
  44. // ConstructFilename
  45. //
  46. bool NumberedFileName::ConstructFilename(LPTSTR pszFile,
  47. DWORD cchFile,
  48. LPCTSTR pszDirectory,
  49. LPCTSTR pszFilename,
  50. LPCTSTR pszNumber,
  51. LPCTSTR pszExtension )
  52. {
  53. if ((pszFile == NULL) || (cchFile == 0))
  54. {
  55. return false;
  56. }
  57. CSimpleString FullFilePath;
  58. *pszFile = TEXT('\0');
  59. if (pszDirectory && *pszDirectory)
  60. {
  61. //
  62. // Start with the directory name
  63. //
  64. FullFilePath += CSimpleString(pszDirectory);
  65. //
  66. // Ensure there is a trailing slash
  67. //
  68. if (!FullFilePath.MatchLastCharacter(TEXT('\\')))
  69. {
  70. FullFilePath += CSimpleString(TEXT("\\"));
  71. }
  72. }
  73. if (pszFilename && *pszFilename)
  74. {
  75. //
  76. // Append the filename
  77. //
  78. FullFilePath += CSimpleString(pszFilename);
  79. }
  80. if (pszNumber && *pszNumber)
  81. {
  82. //
  83. // Append a space
  84. //
  85. FullFilePath += CSimpleString(TEXT(" "));
  86. //
  87. // Append the number to the file name
  88. //
  89. FullFilePath += CSimpleString(pszNumber);
  90. }
  91. if (pszExtension && *pszExtension)
  92. {
  93. //
  94. // Append the extension's . if necessary
  95. //
  96. if (*pszExtension != TEXT('.'))
  97. {
  98. FullFilePath += CSimpleString(TEXT("."));
  99. }
  100. //
  101. // Append the extension
  102. //
  103. FullFilePath += CSimpleString(pszExtension);
  104. }
  105. if ((pszFile) && (cchFile > 0))
  106. {
  107. _tcsncpy(pszFile,
  108. CSimpleStringConvert::NaturalString(FullFilePath).String(),
  109. cchFile - 1);
  110. pszFile[cchFile - 1] = '\0';
  111. }
  112. return(lstrlen(pszFile) != 0);
  113. }
  114. ///////////////////////////////
  115. // FindLowestAvailableFileSequence
  116. //
  117. int NumberedFileName::FindLowestAvailableFileSequence(LPCTSTR pszDirectory,
  118. LPCTSTR pszFilename,
  119. LPCTSTR pszNumberFormat,
  120. LPCTSTR pszExtension,
  121. bool bAllowUnnumberedFile,
  122. int nCount,
  123. int nStart)
  124. {
  125. DBG_FN("NumberedFileName::FindLowestAvailableFileSequence");
  126. if (!pszDirectory ||
  127. !pszFilename ||
  128. !pszNumberFormat ||
  129. !nCount ||
  130. !*pszDirectory ||
  131. !*pszFilename ||
  132. !*pszNumberFormat)
  133. {
  134. return -1;
  135. }
  136. TCHAR szFile[MAX_PATH + 1] = {0};
  137. if (nCount == 1 && bAllowUnnumberedFile)
  138. {
  139. if (ConstructFilename(szFile,
  140. sizeof(szFile) / sizeof(szFile[0]) - 1,
  141. pszDirectory,
  142. pszFilename,
  143. NULL,
  144. pszExtension))
  145. {
  146. if (!DoesFileExist(szFile))
  147. {
  148. // 0 is a special return value that says "Don't put a number on this file"
  149. return 0;
  150. }
  151. }
  152. }
  153. int i = nStart;
  154. //
  155. // Make sure i is a valid number
  156. //
  157. if (i <= 0)
  158. {
  159. i = 1;
  160. }
  161. while (i<0x7FFFFFFF)
  162. {
  163. //
  164. // Assume we'll be able to store the sequence
  165. //
  166. bool bEnoughRoom = true;
  167. for (int j = 0; j < nCount && bEnoughRoom; j++)
  168. {
  169. TCHAR szNumber[31 + 1] = {0};
  170. _sntprintf(szNumber,
  171. sizeof(szNumber) / sizeof(szNumber[0]) - 1,
  172. pszNumberFormat,
  173. i + j);
  174. if (ConstructFilename(szFile,
  175. sizeof(szFile) / sizeof(szFile[0]) - 1,
  176. pszDirectory,
  177. pszFilename,
  178. szNumber,
  179. pszExtension))
  180. {
  181. if (DoesFileExist(szFile))
  182. {
  183. //
  184. // Didn't make it
  185. //
  186. bEnoughRoom = false;
  187. //
  188. // Skip this series. No need to start at the bottom.
  189. //
  190. i += j;
  191. }
  192. }
  193. }
  194. //
  195. // If we made it through, return the base number, otherwise increment by one
  196. //
  197. if (bEnoughRoom)
  198. {
  199. return i;
  200. }
  201. else
  202. {
  203. i++;
  204. }
  205. }
  206. return -1;
  207. }
  208. ///////////////////////////////
  209. // CreateNumberedFileName
  210. //
  211. bool NumberedFileName::CreateNumberedFileName(DWORD dwFlags,
  212. LPTSTR pszPathName,
  213. DWORD cchPathName,
  214. LPCTSTR pszDirectory,
  215. LPCTSTR pszFilename,
  216. LPCTSTR pszNumberFormat,
  217. LPCTSTR pszExtension,
  218. int nNumber )
  219. {
  220. if (nNumber == 0)
  221. {
  222. return ConstructFilename(pszPathName,
  223. cchPathName,
  224. (dwFlags&FlagOmitDirectory) ? NULL : pszDirectory,
  225. pszFilename,
  226. NULL,
  227. (dwFlags&FlagOmitExtension) ? NULL : pszExtension);
  228. }
  229. else
  230. {
  231. TCHAR szNumber[31 + 1] = {0};
  232. if (pszNumberFormat)
  233. {
  234. _sntprintf(szNumber,
  235. sizeof(szNumber)/sizeof(szNumber[0]) - 1,
  236. pszNumberFormat,
  237. nNumber);
  238. //
  239. // Paranoid: NULL terminate
  240. //
  241. szNumber[sizeof(szNumber)/sizeof(szNumber[0]) - 1] = '\0';
  242. }
  243. return ConstructFilename(pszPathName,
  244. cchPathName,
  245. (dwFlags & FlagOmitDirectory) ? NULL : pszDirectory,
  246. pszFilename,
  247. szNumber,
  248. (dwFlags & FlagOmitExtension) ? NULL : pszExtension);
  249. }
  250. }
  251. ///////////////////////////////
  252. // GenerateLowestAvailableNumberedFileName
  253. //
  254. int NumberedFileName::GenerateLowestAvailableNumberedFileName(DWORD dwFlags,
  255. LPTSTR pszPathName,
  256. DWORD cchPathName,
  257. LPCTSTR pszDirectory,
  258. LPCTSTR pszFilename,
  259. LPCTSTR pszNumberFormat,
  260. LPCTSTR pszExtension,
  261. bool bAllowUnnumberedFile,
  262. int nStart )
  263. {
  264. //
  265. // -1 is an error. Default to failure
  266. //
  267. int nResult = -1;
  268. //
  269. // Find the lowest available file number
  270. //
  271. int nLowest = FindLowestAvailableFileSequence(pszDirectory,
  272. pszFilename,
  273. pszNumberFormat,
  274. pszExtension,
  275. bAllowUnnumberedFile,
  276. 1,
  277. nStart);
  278. if (nLowest >= 0)
  279. {
  280. //
  281. // If we can create the filename, return the number of the file
  282. //
  283. if (CreateNumberedFileName(dwFlags,
  284. pszPathName,
  285. cchPathName,
  286. pszDirectory,
  287. pszFilename,
  288. pszNumberFormat,
  289. pszExtension,
  290. nLowest))
  291. {
  292. //
  293. // Return the file's number
  294. //
  295. nResult = nLowest;
  296. }
  297. }
  298. return nResult;
  299. }