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.

364 lines
9.2 KiB

  1. #include "precomp.h"
  2. #include <RegEntry.h>
  3. #include <ConfReg.h>
  4. #include <oprahcom.h>
  5. #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
  6. BOOL NMINTERNAL CanShellExecHttp()
  7. {
  8. RegEntry re(CLASSES_HTTP_KEY, HKEY_LOCAL_MACHINE, FALSE);
  9. return (re.GetError() == ERROR_SUCCESS);
  10. }
  11. BOOL NMINTERNAL CanShellExecMailto()
  12. {
  13. RegEntry re(CLASSES_MAILTO_KEY, HKEY_LOCAL_MACHINE, FALSE);
  14. return (re.GetError() == ERROR_SUCCESS);
  15. }
  16. /* G E T I N S T A L L D I R E C T O R Y */
  17. /*----------------------------------------------------------------------------
  18. %%Function: GetInstallDirectory
  19. Return TRUE if the installation directory was read from the registry.
  20. The string is set empty if the function fails and returns FALSE.
  21. The buffer pointed to by psz is assumed to be at least MAX_PATH characters.
  22. Note that the name is always terminated with a final backslash.
  23. ----------------------------------------------------------------------------*/
  24. BOOL NMINTERNAL GetInstallDirectory(LPTSTR psz)
  25. {
  26. RegEntry reInstall(CONFERENCING_KEY, HKEY_LOCAL_MACHINE);
  27. ASSERT(NULL != psz);
  28. lstrcpyn(psz, reInstall.GetString(REGVAL_INSTALL_DIR), MAX_PATH);
  29. if (_T('\0') == *psz)
  30. return FALSE; // No registry entry was found
  31. // Make sure the directory name has a trailing '\'
  32. // BUGBUG - Don't call CharNext twice in each iteration
  33. for ( ; _T('\0') != *psz; psz = CharNext(psz))
  34. {
  35. if ((_T('\\') == *psz) && (_T('\0') == *CharNext(psz)) )
  36. {
  37. // The path already ends with a backslash
  38. return TRUE;
  39. }
  40. }
  41. // Append a trailing backslash
  42. // BUGBUG - Can't we just append the char in place with an assignment?
  43. lstrcat(psz, _TEXT("\\"));
  44. return TRUE;
  45. }
  46. /* F F I L E E X I S T S */
  47. /*-------------------------------------------------------------------------
  48. %%Function: FFileExists
  49. Return TRUE if the file exists and can be read & written.
  50. -------------------------------------------------------------------------*/
  51. BOOL NMINTERNAL FFileExists(LPCTSTR szFile)
  52. {
  53. HANDLE hFile;
  54. if ((NULL == szFile) || (_T('\0') == *szFile))
  55. return FALSE;
  56. UINT uErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  57. hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  58. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  59. SetErrorMode(uErrorMode); // Restore error mode
  60. if (hFile == INVALID_HANDLE_VALUE)
  61. return FALSE;
  62. CloseHandle(hFile);
  63. return TRUE;
  64. }
  65. /* F D I R E X I S T S */
  66. /*-------------------------------------------------------------------------
  67. %%Function: FDirExists
  68. Return TRUE if the directory exists.
  69. -------------------------------------------------------------------------*/
  70. BOOL NMINTERNAL FDirExists(LPCTSTR szDir)
  71. {
  72. UINT uErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  73. DWORD dwFa = GetFileAttributes(szDir);
  74. SetErrorMode(uErrorMode); // Restore error mode
  75. if (0xFFFFFFFF == dwFa)
  76. return FALSE;
  77. return (0 != (dwFa & FILE_ATTRIBUTE_DIRECTORY));
  78. }
  79. /* F E N S U R E D I R E X I S T S */
  80. /*-------------------------------------------------------------------------
  81. %%Function: FEnsureDirExists
  82. Ensure the Directory exists, creating the entire path if necessary.
  83. Returns FALSE if there was a problem.
  84. -------------------------------------------------------------------------*/
  85. BOOL NMINTERNAL FEnsureDirExists(LPCTSTR szDir)
  86. {
  87. TCHAR szPath[MAX_PATH+1];
  88. TCHAR * pszDirEnd;
  89. TCHAR * pszDirT;
  90. ASSERT(lstrlen(szDir) < MAX_PATH);
  91. if (FDirExists(szDir))
  92. return TRUE; // Nothing to do - already exists
  93. // Work with a copy of the path
  94. lstrcpy(szPath, szDir);
  95. for(pszDirT = szPath, pszDirEnd = &szPath[lstrlen(szPath)];
  96. pszDirT <= pszDirEnd;
  97. pszDirT = CharNext(pszDirT))
  98. {
  99. if ((*pszDirT == _T('\\')) || (pszDirT == pszDirEnd))
  100. {
  101. *pszDirT = _T('\0');
  102. if (!FDirExists(szPath))
  103. {
  104. UINT uErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  105. BOOL fOk = CreateDirectory(szPath, NULL);
  106. SetErrorMode(uErrorMode); // Restore error mode
  107. if (!fOk)
  108. return FALSE;
  109. }
  110. *pszDirT = _T('\\');
  111. }
  112. }
  113. TRACE_OUT(("Created Directory [%s]", szDir));
  114. return TRUE;
  115. }
  116. /* E X T R A C T F I L E N A M E */
  117. /*-------------------------------------------------------------------------
  118. %%Function: ExtractFileName, ExtractFileNameA
  119. Extracts the file name from a path name.
  120. Returns a pointer to file name in path string.
  121. -------------------------------------------------------------------------*/
  122. LPCTSTR NMINTERNAL ExtractFileName(LPCTSTR pcszPathName)
  123. {
  124. LPCTSTR pcszLastComponent;
  125. LPCTSTR pcsz;
  126. ASSERT(IS_VALID_STRING_PTR(pcszPathName, CSTR));
  127. for (pcszLastComponent = pcsz = pcszPathName;
  128. *pcsz;
  129. pcsz = CharNext(pcsz))
  130. {
  131. if (IS_SLASH(*pcsz) || *pcsz == COLON)
  132. pcszLastComponent = CharNext(pcsz);
  133. }
  134. ASSERT(IsValidPath(pcszLastComponent));
  135. return(pcszLastComponent);
  136. }
  137. #if defined(UNICODE)
  138. LPCSTR NMINTERNAL ExtractFileNameA(LPCSTR pcszPathName)
  139. {
  140. LPCSTR pcszLastComponent;
  141. LPCSTR pcsz;
  142. ASSERT(IS_VALID_STRING_PTR_A(pcszPathName, CSTR));
  143. for (pcszLastComponent = pcsz = pcszPathName;
  144. *pcsz;
  145. pcsz = CharNextA(pcsz))
  146. {
  147. if (IS_SLASH(*pcsz) || *pcsz == COLON)
  148. pcszLastComponent = CharNextA(pcsz);
  149. }
  150. ASSERT(IsValidPathA(pcszLastComponent));
  151. return(pcszLastComponent);
  152. }
  153. #endif // defined(UNICODE)
  154. /* S A N I T I Z E F I L E N A M E */
  155. /*-------------------------------------------------------------------------
  156. %%Function: SanitizeFileName
  157. -------------------------------------------------------------------------*/
  158. BOOL NMINTERNAL SanitizeFileName(LPTSTR psz)
  159. {
  160. if (NULL == psz)
  161. return FALSE;
  162. while (*psz)
  163. {
  164. switch (*psz)
  165. {
  166. case _T('\\'):
  167. case _T('\"'):
  168. case _T('/'):
  169. case _T(':'):
  170. case _T('*'):
  171. case _T('?'):
  172. case _T('<'):
  173. case _T('>'):
  174. case _T('|'):
  175. *psz = _T('_');
  176. default:
  177. break;
  178. }
  179. psz = ::CharNext(psz);
  180. }
  181. return TRUE;
  182. }
  183. ///////////////////////////////////////////////////////////////////////////
  184. /* C R E A T E N E W F I L E */
  185. /*----------------------------------------------------------------------------
  186. %%Function: CreateNewFile
  187. Attempt to create a new file.
  188. Note this returns either 0 (success)
  189. or the result from GetLastError (usually ERROR_FILE_EXISTS)
  190. ----------------------------------------------------------------------------*/
  191. DWORD CreateNewFile(LPTSTR pszFile)
  192. {
  193. DWORD errRet;
  194. HANDLE hFile;
  195. if (lstrlen(pszFile) >= MAX_PATH)
  196. {
  197. // don't allow long path/filenames
  198. return 1;
  199. }
  200. SetLastError(0);
  201. UINT uErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  202. hFile = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, 0,
  203. NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  204. SetErrorMode(uErrorMode); // Restore error mode
  205. errRet = GetLastError();
  206. if (hFile != INVALID_HANDLE_VALUE)
  207. {
  208. CloseHandle(hFile);
  209. }
  210. return errRet;
  211. }
  212. /* F C R E A T E N E W F I L E */
  213. /*-------------------------------------------------------------------------
  214. %%Function: FCreateNewFile
  215. Create a new file in a directory, with a name and extension.
  216. Returns the full path name in the buffer.
  217. -------------------------------------------------------------------------*/
  218. BOOL FCreateNewFile(LPCTSTR pcszPath, LPCTSTR pcszName, LPCTSTR pcszExt, LPTSTR pszResult, int cchMax)
  219. {
  220. TCHAR szFile[MAX_PATH*2];
  221. lstrcpyn(szFile, pcszPath, ARRAYSIZE(szFile));
  222. if (!FEnsureDirName(szFile))
  223. return FALSE;
  224. LPTSTR psz = szFile + lstrlen(szFile);
  225. lstrcpyn(psz, pcszName, (int)(ARRAYSIZE(szFile) - (psz - szFile)));
  226. SanitizeFileName(psz);
  227. if(lstrlen(psz) + lstrlen(pcszExt) < (ARRAYSIZE(szFile) - 1))
  228. {
  229. lstrcat(psz, pcszExt);
  230. }
  231. else
  232. {
  233. return FALSE;
  234. }
  235. DWORD dwErr = CreateNewFile(szFile);
  236. if (0 != dwErr)
  237. {
  238. // Create a duplicate filename
  239. psz += lstrlen(pcszName);
  240. for (int iFile = 2; iFile < 999; iFile++)
  241. {
  242. wsprintf(psz, TEXT(" (%d).%s"), iFile, pcszExt);
  243. if (ERROR_FILE_EXISTS != (dwErr = CreateNewFile(szFile)) )
  244. break;
  245. }
  246. if (0 != dwErr)
  247. {
  248. WARNING_OUT(("Unable to create duplicate filename (err=%d)", dwErr));
  249. return FALSE;
  250. }
  251. }
  252. if (cchMax > lstrlen(szFile))
  253. {
  254. lstrcpy(pszResult, szFile);
  255. }
  256. else
  257. {
  258. // try and make the full name fit within the buffer
  259. dwErr = GetShortPathName(szFile, pszResult, cchMax);
  260. if ((0 == dwErr) || (dwErr >= MAX_PATH))
  261. return FALSE;
  262. }
  263. return TRUE;
  264. }
  265. /* F E N S U R E D I R N A M E */
  266. /*-------------------------------------------------------------------------
  267. %%Function: FEnsureDirName
  268. -------------------------------------------------------------------------*/
  269. BOOL FEnsureDirName(LPTSTR pszPath)
  270. {
  271. if (NULL == pszPath)
  272. return FALSE;
  273. LPTSTR pszCurr = pszPath;
  274. // Make sure the directory name has a trailing '\'
  275. for ( ; ; )
  276. {
  277. LPTSTR pszNext = CharNext(pszCurr);
  278. if (*pszNext == _T('\0'))
  279. {
  280. if (_T('\\') != *pszCurr)
  281. {
  282. *pszNext++ = _T('\\');
  283. *pszNext = _T('\0');
  284. }
  285. break;
  286. }
  287. pszCurr = pszNext;
  288. }
  289. return FEnsureDirExists(pszPath);
  290. }