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.

288 lines
7.0 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include "verpriv.h"
  5. #include "wchar.h"
  6. /* Determine if a file is in use by Windows
  7. */
  8. BOOL FileInUse(LPWSTR lpszFilePath, LPWSTR lpszFileName)
  9. {
  10. HANDLE hFile;
  11. BOOL bResult = FALSE;
  12. //
  13. // Attempt to open the file exclusively.
  14. //
  15. hFile = CreateFile(lpszFilePath,
  16. GENERIC_WRITE | GENERIC_READ,
  17. 0,
  18. NULL,
  19. OPEN_EXISTING,
  20. FILE_ATTRIBUTE_NORMAL,
  21. NULL);
  22. if (hFile == INVALID_HANDLE_VALUE) {
  23. //
  24. // If the last error is access denied,
  25. // then the file is in use by someone
  26. // else. Return TRUE in this case.
  27. //
  28. if (GetLastError() == ERROR_SHARING_VIOLATION)
  29. bResult = TRUE;
  30. } else {
  31. //
  32. // CreateFile successfully opened the file.
  33. // Close the handle and return FALSE.
  34. //
  35. CloseHandle(hFile);
  36. }
  37. return bResult;
  38. }
  39. /* Take a Dir and Filename and make a full path from them
  40. */
  41. DWORD MakeFileName(LPWSTR lpDst, LPWSTR lpDir, LPWSTR lpFile, int cchDst)
  42. {
  43. DWORD wDirLen;
  44. WCHAR cTemp;
  45. wcsncpy(lpDst, lpDir, cchDst);
  46. lpDst[cchDst-1] = TEXT('\0');
  47. wDirLen=wcslen(lpDst);
  48. if ( wDirLen && (cTemp=*(lpDst+wDirLen-1))!=TEXT('\\') && cTemp!=TEXT(':'))
  49. lpDst[wDirLen++] = TEXT('\\');
  50. wcsncpy(lpDst+wDirLen, lpFile, cchDst - wDirLen);
  51. lpDst[cchDst-1] = TEXT('\0');
  52. return(wDirLen);
  53. }
  54. /* Given a filename and a list of directories, find the first directory
  55. * that contains the file, and copy it into the buffer. Note that in the
  56. * library version, you can give an environment style path, but not in the
  57. * DLL version.
  58. */
  59. INT
  60. GetDirOfFile(LPWSTR lpszFileName,
  61. LPWSTR lpszPathName,
  62. DWORD wSize,
  63. LPWSTR *lplpszDirs)
  64. {
  65. WCHAR szFileName[_MAX_PATH];
  66. HANDLE hfRes;
  67. INT nFileLen = 0;
  68. INT nPathLen = 0;
  69. BOOL bDoDefaultOpen = TRUE;
  70. LPWSTR *lplpFirstDir;
  71. LPWSTR lpszDir;
  72. nFileLen = wcslen(lpszFileName);
  73. for (lplpFirstDir=lplpszDirs; *lplpFirstDir && bDoDefaultOpen;
  74. ++lplpFirstDir)
  75. {
  76. lpszDir = *lplpFirstDir;
  77. if (nFileLen+wcslen(lpszDir) >= _MAX_PATH-1)
  78. continue;
  79. MakeFileName(szFileName, lpszDir, lpszFileName, ARRAYSIZE(szFileName));
  80. TryOpen:
  81. nPathLen = 0; // Re-init for this path.
  82. if ((hfRes = CreateFile(szFileName, GENERIC_READ,
  83. FILE_SHARE_READ, NULL, OPEN_EXISTING,
  84. FILE_FLAG_SEQUENTIAL_SCAN, NULL)) != (HANDLE)-1)
  85. {
  86. CloseHandle(hfRes);
  87. for (lpszDir=szFileName; *lpszDir; lpszDir++)
  88. if (*lpszDir == TEXT('\\'))
  89. nPathLen = (INT)(lpszDir - (LPWSTR)szFileName);
  90. /* This gets rid of the '\' if this is not the root of a drive
  91. */
  92. if (nPathLen <= 3)
  93. ++nPathLen;
  94. /* Account for the terminating NULL, and make sure wSize is in bounds
  95. * then NULL terminate the string in the appropriate place so that
  96. * we can just do an wcscpy.
  97. */
  98. --wSize;
  99. szFileName[(int)wSize<nPathLen ? wSize : nPathLen] = 0;
  100. wcscpy(lpszPathName, szFileName);
  101. return(nPathLen);
  102. }
  103. }
  104. if (bDoDefaultOpen)
  105. {
  106. bDoDefaultOpen = FALSE;
  107. wcscpy(szFileName, lpszFileName);
  108. goto TryOpen;
  109. }
  110. return(0);
  111. }
  112. #define GetWindowsDir(x,y,z) GetWindowsDirectory(y,z)
  113. #define GetSystemDir(x,y,z) GetSystemDirectory(y,z)
  114. DWORD
  115. APIENTRY
  116. VerFindFileW(
  117. DWORD wFlags,
  118. LPWSTR lpszFileName,
  119. LPWSTR lpszWinDir,
  120. LPWSTR lpszAppDir,
  121. LPWSTR lpszCurDir,
  122. PUINT puCurDirLen,
  123. LPWSTR lpszDestDir,
  124. PUINT puDestDirLen
  125. )
  126. {
  127. static WORD wSharedDirLen = 0;
  128. static WCHAR gszSharedDir[_MAX_PATH];
  129. WCHAR szSysDir[_MAX_PATH], cTemp;
  130. WCHAR szWinDir[_MAX_PATH];
  131. WCHAR szCurDir[_MAX_PATH];
  132. LPWSTR lpszDir, lpszDirs[4];
  133. WORD wDestLen, wWinLen, wRetVal = 0, wTemp;
  134. int nRet;
  135. #ifdef WX86
  136. // Save a copy of the 'from Wx86' flag and clear it.
  137. BOOLEAN UseKnownWx86Dll = NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll;
  138. NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  139. #endif
  140. /* We want to really look in the Windows directory; we don't trust the app
  141. */
  142. GetWindowsDir(lpszWinDir ? lpszWinDir : "", szWinDir, _MAX_PATH);
  143. lpszWinDir = szWinDir;
  144. #ifdef WX86
  145. NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = UseKnownWx86Dll;
  146. #endif
  147. if(!GetSystemDir( lpszWinDir, szSysDir, _MAX_PATH))
  148. wcscpy(szSysDir, lpszWinDir);
  149. #ifdef WX86
  150. NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  151. #endif
  152. if (wFlags & VFFF_ISSHAREDFILE) {
  153. lpszDirs[0] = lpszWinDir;
  154. lpszDirs[1] = szSysDir;
  155. lpszDirs[2] = lpszAppDir;
  156. } else {
  157. lpszDirs[0] = lpszAppDir;
  158. lpszDirs[1] = lpszWinDir;
  159. lpszDirs[2] = szSysDir;
  160. }
  161. lpszDirs[3] = NULL;
  162. if (!(wTemp=(WORD)GetDirOfFile(lpszFileName, szCurDir, _MAX_PATH, lpszDirs)))
  163. *szCurDir = 0;
  164. if (*puCurDirLen > wTemp)
  165. wcscpy(lpszCurDir, szCurDir);
  166. else
  167. wRetVal |= VFF_BUFFTOOSMALL;
  168. *puCurDirLen = wTemp + 1;
  169. if (lpszDestDir)
  170. {
  171. if (wFlags & VFFF_ISSHAREDFILE)
  172. {
  173. if (!wSharedDirLen)
  174. {
  175. if ((wWinLen = (WORD)wcslen(lpszWinDir)) &&
  176. *(lpszWinDir-1)==TEXT('\\'))
  177. {
  178. if (szSysDir[wWinLen-1] == TEXT('\\'))
  179. goto doCompare;
  180. }
  181. else if (szSysDir[wWinLen] == TEXT('\\'))
  182. {
  183. doCompare:
  184. cTemp = szSysDir[wWinLen];
  185. szSysDir[wWinLen] = 0;
  186. nRet = _wcsicmp(lpszWinDir, szSysDir);
  187. szSysDir[wWinLen] = cTemp;
  188. if(nRet)
  189. goto doCopyWinDir;
  190. wcscpy(gszSharedDir, szSysDir);
  191. }
  192. else
  193. {
  194. doCopyWinDir:
  195. wcscpy(gszSharedDir, lpszWinDir);
  196. }
  197. wSharedDirLen = (WORD)wcslen(gszSharedDir);
  198. }
  199. wDestLen = wSharedDirLen;
  200. lpszDir = gszSharedDir;
  201. }
  202. else
  203. {
  204. wDestLen = (WORD)wcslen(lpszAppDir);
  205. lpszDir = lpszAppDir;
  206. }
  207. if (*puDestDirLen > wDestLen)
  208. {
  209. wcscpy(lpszDestDir, lpszDir);
  210. if ((wWinLen = (WORD)wcslen(lpszDestDir)) &&
  211. *(lpszDestDir-1)==TEXT('\\'))
  212. lpszDestDir[wWinLen-1] = 0;
  213. if (_wcsicmp(lpszCurDir, lpszDestDir))
  214. wRetVal |= VFF_CURNEDEST;
  215. }
  216. else
  217. wRetVal |= VFF_BUFFTOOSMALL;
  218. *puDestDirLen = wDestLen + 1;
  219. }
  220. if (*szCurDir)
  221. {
  222. MakeFileName(szSysDir, szCurDir, lpszFileName, ARRAYSIZE(szSysDir));
  223. if (FileInUse(szSysDir, lpszFileName))
  224. wRetVal |= VFF_FILEINUSE;
  225. }
  226. return(wRetVal);
  227. }
  228. /*
  229. * DWORD
  230. * APIENTRY
  231. * VerLanguageNameW(
  232. * DWORD wLang,
  233. * LPWSTR szLang,
  234. * DWORD wSize)
  235. *
  236. * This routine was moved to NLSLIB.LIB so that it uses the WINNLS.RC file.
  237. * NLSLIB.LIB is part of KERNEL32.DLL.
  238. */