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.

324 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft OLE
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997.
  5. //
  6. // File: ntutil.cpp
  7. //
  8. // Contents: Utility functions for NTFS drives.
  9. // These functions will probably not be
  10. // available for Mac, Win9x, so should be
  11. // stubbed out in the header file as such.
  12. //
  13. // Functions:
  14. // ConversionVerification
  15. // VerifyNssfile
  16. //
  17. // History: 01/19/98 SCousens Created
  18. //
  19. //--------------------------------------------------------------------------
  20. #include <dfheader.hxx>
  21. #pragma hdrstop
  22. // Debug Object declaration
  23. DH_DECLARE;
  24. // Must be at least NT5 (not mac, not win9x, not nt4 etc)
  25. #if defined(_WIN32_WINNT) && (_WIN32_WINNT>=0x0500)
  26. /*******************************************************************/
  27. /* */
  28. /* WARNING: */
  29. /* ConversionVerification, VerifyNssfile */
  30. /* must be the LAST functions in this file. */
  31. /* We redefine stuff that must not affect the rest */
  32. /* of the functions. */
  33. /* of the functions. */
  34. /* */
  35. /*******************************************************************/
  36. #ifdef _HOOK_STGAPI_
  37. #undef StgCreateDocfile
  38. #undef StgOpenStorage
  39. #endif /* _HOOK_STGAPI_ */
  40. //+-------------------------------------------------------------------------
  41. // Function: ConversionVerification
  42. //
  43. // Synopsis: Opens a nssfile as docfile and then as nssfile
  44. // and calculates CRC each time. If CRC is different
  45. // then there is a problem with the conversion driver
  46. //
  47. // Arguments: [pFileName] - Name of Docfile
  48. // [dwCRCexp] - Expected CRC (default=0)
  49. //
  50. // Returns: S_OK if all went well and CRCs match
  51. // or E_FAIL if something else went wrong
  52. // (CRCs dont match, ulRef not 0 after Release)
  53. //
  54. // History: 28-Jan-97 SCousens Created.
  55. //
  56. // Notes: - NSSFile must previously be closed, or access violations
  57. // may occur calculating CRC.
  58. //--------------------------------------------------------------------------
  59. HRESULT ConversionVerification (LPTSTR pFileName, DWORD dwCRCexp)
  60. {
  61. DWORD dwCRCdf = 0, dwCRCnss = 0;
  62. IStorage *pIStorage;
  63. HRESULT hr = S_OK;
  64. ULONG ul;
  65. LPOLESTR pOleStrTemp = NULL;
  66. DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ConversionVerification"));
  67. DH_VDATESTRINGPTR (pFileName);
  68. // Convert TCHAR to OLECHAR
  69. hr = TStringToOleString(pFileName, &pOleStrTemp);
  70. DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
  71. // Open as docfile, calc CRC for file and close it.
  72. if(S_OK == hr)
  73. {
  74. hr = StgOpenStorageEx (pOleStrTemp,
  75. STGM_READ | STGM_SHARE_EXCLUSIVE,
  76. STGFMT_DOCFILE,
  77. 0,
  78. NULL,
  79. NULL,
  80. IID_IStorage,
  81. (void**)&pIStorage);
  82. DH_HRCHECK (hr, TEXT("Cnv:StgOpenStorageEx"));
  83. if (S_OK == hr)
  84. {
  85. hr = CalculateCRCForDocFile(pIStorage,
  86. VERIFY_INC_TOPSTG_NAME,
  87. &dwCRCdf);
  88. DH_HRCHECK (hr, TEXT("CalculateCRCForDocFile"));
  89. }
  90. if (S_OK != hr || 0 == dwCRCdf)
  91. {
  92. DH_LOG((LOG_INFO, TEXT("Cnv:CalculateCRCForDocFile on docfile failed, hr=0x%lx.\n"), hr));
  93. }
  94. if (NULL != pIStorage)
  95. {
  96. ul = pIStorage->Release ();
  97. DH_ASSERT (0 == ul);
  98. pIStorage = NULL;
  99. }
  100. }
  101. // Open normally (as nssfile), calc CRC for the file close it.
  102. if (S_OK == hr)
  103. {
  104. hr = StgOpenStorage (pOleStrTemp,
  105. NULL,
  106. STGM_READ | STGM_SHARE_EXCLUSIVE,
  107. NULL,
  108. 0,
  109. &pIStorage);
  110. DH_HRCHECK (hr, TEXT("Cnv:StgOpenStorage"));
  111. if (S_OK == hr)
  112. {
  113. hr = CalculateCRCForDocFile(pIStorage,
  114. VERIFY_INC_TOPSTG_NAME,
  115. &dwCRCnss);
  116. DH_HRCHECK (hr, TEXT("CalculateCRCForDocFile"));
  117. }
  118. if (S_OK != hr || 0 == dwCRCnss)
  119. {
  120. DH_LOG((LOG_INFO, TEXT("Cnv:CalculateCRCForDocFile on nssfile failed, hr=0x%lx.\n"), hr));
  121. }
  122. if (NULL != pIStorage)
  123. {
  124. ul = pIStorage->Release ();
  125. DH_ASSERT (0 == ul);
  126. pIStorage = NULL;
  127. }
  128. }
  129. // spew
  130. if (S_OK == hr &&
  131. dwCRCnss == dwCRCdf &&
  132. 0 != dwCRCdf &&
  133. (0 == dwCRCexp || dwCRCexp == dwCRCdf))
  134. {
  135. DH_LOG((LOG_INFO, TEXT("Conversion verification passed.\n")) );
  136. }
  137. else
  138. {
  139. hr = (S_OK != hr) ? hr : E_FAIL; //set it only if not already set.
  140. DH_LOG((LOG_INFO,
  141. TEXT("Conversion verification failed, hr=0x%lx.\n"),
  142. hr) );
  143. }
  144. if (NULL != pOleStrTemp)
  145. {
  146. delete pOleStrTemp;
  147. pOleStrTemp = NULL;
  148. }
  149. return hr;
  150. }
  151. //+-------------------------------------------------------------------------
  152. // Function: VerifyNssfile
  153. //
  154. // Synopsis: Verify an nssfile is indeed an nssfile by checking:
  155. // 1. reparse point is set (spew if not)
  156. // 2. header is valid (spew if df or unknown, and set hr)
  157. // Verify the reparse point is set.
  158. // Open the file directly with REPARSE flag (to prevent cnss from
  159. // converting it). Read the header and make sure it looks like a
  160. // real nssfile by checking the file signatures.
  161. //
  162. // Arguments: [pszPathname] - full path to the file to be checked
  163. //
  164. // Returns: S_OK, else some sort of error.
  165. // We set the following if file is df or unknown
  166. // ERROR_INVALID_DATA - if file is a DOCFILE
  167. // 13L - The data is invalid
  168. // ERROR_FILE_INVALID - if file is UNKNOWN (not df or nss)
  169. // 1006L - The volume for a file has been externally
  170. // altered so that the opened file is no longer valid
  171. // ERROR_INVALID_EA_NAME - no reparse point (if others valid)
  172. // 254L - The specified extended attribute name was invalid.
  173. //
  174. // History: 24-Jul-97 SCousens Created.
  175. //
  176. // Notes: - NSSFile must previously be closed, or file share
  177. // access violations may occur reading the header.
  178. //--------------------------------------------------------------------------
  179. #define NSSFILE_SIGNATURE 0x444D4F30
  180. #define DOCFILE_SIGNATURE1 0xE011CFD0 //0xD0CF11E0 little endian
  181. #define DOCFILE_SIGNATURE2 0xE11AB1A1 //0xA1B11AE1 little endian
  182. HRESULT VerifyNssfile (LPTSTR pszPathname)
  183. {
  184. HRESULT hr = S_OK;
  185. HANDLE hnd;
  186. ULONG culRead;
  187. ULONG ulAttr;
  188. struct _structFileHeader {
  189. ULONG ulSig1;
  190. ULONG ulSig2;
  191. } sFileHeader;
  192. DH_FUNCENTRY (&hr, DH_LVL_DFLIB, TEXT("VerifyNssfile"));
  193. /* check the file attributes and look for reparse attribute */
  194. ulAttr = GetFileAttributes (pszPathname);
  195. DH_TRACE ((DH_LVL_DFLIB,
  196. TEXT("VerifyNssfile; Attributes retrieved:%#lx"),
  197. ulAttr));
  198. if ((ULONG)-1 == ulAttr)
  199. {
  200. DH_TRACE ((DH_LVL_ERROR,
  201. TEXT("VerifyNssfile; Unable to get attributes for %s"),
  202. pszPathname));
  203. hr = HRESULT_FROM_WIN32(GetLastError());
  204. DH_HRCHECK (hr, TEXT("GetFileAttributes"));
  205. return hr;
  206. }
  207. /* attempt to open the file */
  208. hnd = CreateFile(pszPathname,
  209. GENERIC_READ,
  210. FILE_SHARE_READ,
  211. NULL, // security descriptor
  212. OPEN_EXISTING,
  213. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT,
  214. NULL); //hTemplateFile
  215. if (INVALID_HANDLE_VALUE == hnd)
  216. {
  217. hr = HRESULT_FROM_WIN32(GetLastError());
  218. }
  219. DH_HRCHECK (hr, TEXT("CreateFile"));
  220. /* if we succeeded, read the header */
  221. if (S_OK == hr)
  222. {
  223. BOOL fErr;
  224. fErr = ReadFile (hnd, &sFileHeader, sizeof (sFileHeader), &culRead, NULL);
  225. if (FALSE == fErr)
  226. {
  227. hr = HRESULT_FROM_WIN32(GetLastError());
  228. }
  229. DH_HRCHECK (hr, TEXT("ReadFile"));
  230. DH_TRACE ((DH_LVL_DFLIB, TEXT("Read %ld bytes from file"), culRead));
  231. }
  232. /* check the header looks like an nss header */
  233. if (S_OK == hr)
  234. {
  235. if (sFileHeader.ulSig1 != NSSFILE_SIGNATURE)
  236. {
  237. if (sFileHeader.ulSig1 == DOCFILE_SIGNATURE1 &&
  238. sFileHeader.ulSig2 == DOCFILE_SIGNATURE2)
  239. {
  240. hr = ERROR_INVALID_DATA;
  241. DH_TRACE ((DH_LVL_TRACE1, TEXT("WARNING!!! VerifyNssfile; File appears to be a DOCFILE")));
  242. }
  243. else
  244. {
  245. hr = ERROR_FILE_INVALID;
  246. DH_TRACE ((DH_LVL_TRACE1, TEXT("WARNING!!! VerifyNssfile; File is INVALID nssfile or docfile!")));
  247. }
  248. }
  249. else
  250. {
  251. DH_TRACE ((DH_LVL_DFLIB, TEXT("VerifyNssfile; File appears to be valid nssfile")));
  252. }
  253. }
  254. // If nssfile, but no reparse point, its still not valid!
  255. // It is impossible to have an nssfile with a reparse
  256. // point on an NTFS4 volume.
  257. // It is impossible to have an nssfile on a FAT volume.
  258. if (0 == (FILE_ATTRIBUTE_REPARSE_POINT & ulAttr))
  259. {
  260. DH_TRACE ((DH_LVL_TRACE1,
  261. TEXT("WARNING!!! VerifyNssfile; File *NOT* have reparse point set!")));
  262. if (S_OK == hr)
  263. {
  264. hr = ERROR_INVALID_EA_NAME;
  265. }
  266. }
  267. // close the file
  268. if (INVALID_HANDLE_VALUE != hnd)
  269. {
  270. HRESULT hr2 = S_OK;
  271. if (FALSE == CloseHandle(hnd))
  272. {
  273. hr2 = HRESULT_FROM_WIN32(GetLastError());
  274. }
  275. DH_HRCHECK (hr2, TEXT("CloseHandle"));
  276. }
  277. // if there is a problem, say what file caused it.
  278. if (S_OK != hr)
  279. {
  280. DH_TRACE ((DH_LVL_TRACE1,
  281. TEXT("WARNING!!! File causing problem: %s"),
  282. pszPathname));
  283. }
  284. return hr;
  285. }
  286. /*******************************************************************/
  287. /* */
  288. /* WARNING: */
  289. /* ConversionVerification, VerifyNssfile */
  290. /* must be the LAST function in this file. */
  291. /* We redefine stuff that must not affect the rest */
  292. /* of the functions. */
  293. /* */
  294. /*******************************************************************/
  295. #endif // WINNT5+