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.

350 lines
7.8 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: finder.c
  7. //
  8. // Description: This module contains support routines for the finder
  9. // category API's for the AFP server service
  10. //
  11. // History:
  12. // Sept 30,1993. NarenG Created original version.
  13. //
  14. #include "afpsvcp.h"
  15. BOOL
  16. IsTargetNTFS(
  17. IN LPWSTR lpwsPath
  18. );
  19. DWORD
  20. CopyStream(
  21. IN HANDLE hSrc,
  22. IN HANDLE hDst
  23. );
  24. #define AFP_RESC_STREAM TEXT(":AFP_Resource")
  25. //**
  26. //
  27. // Call: AfpAdminrFinderSetInfo
  28. //
  29. // Returns: NO_ERROR
  30. // ERROR_ACCESS_DENIED
  31. // non-zero returns from AfpServerIOCtrl
  32. //
  33. // Description: This routine communicates with the AFP FSD to implement
  34. // the AfpAdminFinderSetInfo function.
  35. //
  36. DWORD
  37. AfpAdminrFinderSetInfo(
  38. IN AFP_SERVER_HANDLE hServer,
  39. IN LPWSTR pType,
  40. IN LPWSTR pCreator,
  41. IN LPWSTR pData,
  42. IN LPWSTR pResource,
  43. IN LPWSTR pTarget,
  44. IN DWORD dwParmNum
  45. )
  46. {
  47. AFP_REQUEST_PACKET AfpSrp;
  48. DWORD dwRetCode = NO_ERROR, dwRetryCount = 0;
  49. AFP_FINDER_INFO AfpFinderInfo;
  50. LPBYTE pAfpFinderInfoSR = NULL;
  51. DWORD cbAfpFinderInfoSRSize;
  52. DWORD dwAccessStatus=0;
  53. HANDLE hTarget = INVALID_HANDLE_VALUE;
  54. HANDLE hDataSrc = INVALID_HANDLE_VALUE;
  55. HANDLE hResourceSrc = INVALID_HANDLE_VALUE;
  56. LPWSTR lpwsResourceFork;
  57. BOOLEAN fCreatedFile = FALSE;
  58. // Check if caller has access
  59. //
  60. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  61. {
  62. AFP_PRINT(( "SFMSVC: AfpAdminrFinderSetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  63. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  64. dwRetCode, EVENTLOG_ERROR_TYPE );
  65. return( ERROR_ACCESS_DENIED );
  66. }
  67. if ( dwAccessStatus )
  68. {
  69. AFP_PRINT(( "SFMSVC: AfpAdminrFinderSetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  70. return( ERROR_ACCESS_DENIED );
  71. }
  72. if ( wcsstr( pTarget, (LPWSTR)TEXT(":\\") ) == NULL )
  73. return( ERROR_INVALID_NAME );
  74. if ( !IsTargetNTFS( pTarget ) )
  75. return( (DWORD)AFPERR_UnsupportedFS );
  76. //
  77. // Impersonate the client while we read/write the fork data
  78. //
  79. dwRetCode = RpcImpersonateClient( NULL );
  80. if ( dwRetCode != RPC_S_OK )
  81. {
  82. return(I_RpcMapWin32Status( dwRetCode ));
  83. }
  84. // open the data source file if one was specified
  85. //
  86. if ( STRLEN( pData ) > 0 ){
  87. hDataSrc = CreateFile(pData, GENERIC_READ, FILE_SHARE_READ, NULL,
  88. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  89. if (hDataSrc == INVALID_HANDLE_VALUE) {
  90. RpcRevertToSelf();
  91. return( GetLastError() );
  92. }
  93. // open the target file's data stream if the file exists,
  94. // otherwise create the file
  95. //
  96. hTarget = CreateFile(pTarget, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  97. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  98. if (hTarget == INVALID_HANDLE_VALUE) {
  99. dwRetCode = GetLastError();
  100. CloseHandle(hDataSrc);
  101. RpcRevertToSelf();
  102. return( dwRetCode );
  103. }
  104. // Figure out if we just created a new file
  105. if (GetLastError() == 0)
  106. {
  107. fCreatedFile = TRUE;
  108. }
  109. SetFilePointer(hTarget,0,NULL,FILE_BEGIN);
  110. SetEndOfFile(hTarget);
  111. // Read the source data and write it to target data stream
  112. //
  113. SetLastError(NO_ERROR);
  114. dwRetCode = CopyStream(hDataSrc, hTarget);
  115. CloseHandle(hDataSrc);
  116. CloseHandle(hTarget);
  117. if (dwRetCode != NO_ERROR) {
  118. RpcRevertToSelf();
  119. return( dwRetCode );
  120. }
  121. }
  122. // open the resource source file if one was specified
  123. //
  124. if ( STRLEN( pResource ) > 0 ) {
  125. hResourceSrc = CreateFile( pResource, GENERIC_READ, FILE_SHARE_READ,
  126. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  127. NULL);
  128. if (hResourceSrc == INVALID_HANDLE_VALUE) {
  129. RpcRevertToSelf();
  130. return( GetLastError() );
  131. }
  132. lpwsResourceFork = LocalAlloc( LPTR,
  133. (STRLEN(pTarget)+
  134. STRLEN(AFP_RESC_STREAM)+1)
  135. * sizeof( WCHAR ) );
  136. if ( lpwsResourceFork == NULL ) {
  137. CloseHandle(hResourceSrc);
  138. RpcRevertToSelf();
  139. return( ERROR_NOT_ENOUGH_MEMORY );
  140. }
  141. // Open the target resource fork
  142. //
  143. STRCPY(lpwsResourceFork, pTarget );
  144. STRCAT(lpwsResourceFork, AFP_RESC_STREAM);
  145. hTarget = CreateFile(lpwsResourceFork, GENERIC_WRITE, FILE_SHARE_READ,
  146. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  147. if (hTarget == INVALID_HANDLE_VALUE) {
  148. dwRetCode = GetLastError();
  149. LocalFree( lpwsResourceFork );
  150. CloseHandle(hResourceSrc);
  151. RpcRevertToSelf();
  152. return( dwRetCode );
  153. }
  154. LocalFree( lpwsResourceFork );
  155. // Assume we created a new file (datafork) in the process, there is
  156. // no way to tell for sure since creating a new resource fork will
  157. // not tell us whether or not the datafork already existed or not
  158. fCreatedFile = TRUE;
  159. // Read the source resource and write it to target resource stream
  160. //
  161. SetLastError(NO_ERROR);
  162. dwRetCode = CopyStream(hResourceSrc, hTarget);
  163. CloseHandle(hResourceSrc);
  164. CloseHandle(hTarget);
  165. if (dwRetCode != NO_ERROR) {
  166. RpcRevertToSelf();
  167. return( dwRetCode );
  168. }
  169. }
  170. //
  171. // Revert back to LocalSystem context
  172. //
  173. RpcRevertToSelf();
  174. if ( dwParmNum & ( AFP_FD_PARMNUM_TYPE | AFP_FD_PARMNUM_CREATOR ) ){
  175. dwRetCode = NO_ERROR;
  176. AfpFinderInfo.afpfd_path = pTarget;
  177. if ( dwParmNum & AFP_FD_PARMNUM_TYPE )
  178. STRCPY( AfpFinderInfo.afpfd_type, pType );
  179. else
  180. AfpFinderInfo.afpfd_type[0] = TEXT( '\0' );
  181. if ( dwParmNum & AFP_FD_PARMNUM_CREATOR )
  182. STRCPY( AfpFinderInfo.afpfd_creator, pCreator );
  183. else
  184. AfpFinderInfo.afpfd_creator[0] = TEXT( '\0' );
  185. // Make this buffer self-relative.
  186. //
  187. if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)&AfpFinderInfo,
  188. sizeof(SETINFOREQPKT),
  189. AFP_FINDER_STRUCT,
  190. &pAfpFinderInfoSR,
  191. &cbAfpFinderInfoSRSize ))
  192. return( dwRetCode );
  193. // Make IOCTL to set info
  194. //
  195. AfpSrp.dwRequestCode = OP_FINDER_SET;
  196. AfpSrp.dwApiType = AFP_API_TYPE_SETINFO;
  197. AfpSrp.Type.SetInfo.pInputBuf = pAfpFinderInfoSR;
  198. AfpSrp.Type.SetInfo.cbInputBufSize = cbAfpFinderInfoSRSize;
  199. AfpSrp.Type.SetInfo.dwParmNum = dwParmNum;
  200. // Since there will be a delay between the time the change
  201. // notify comes into the server for the new file, and the
  202. // time it is actually processed by the server, we need to
  203. // put in a delay and retry to give the server a chance to
  204. // cache the new file
  205. if (fCreatedFile)
  206. {
  207. Sleep( 2000 );
  208. }
  209. do
  210. {
  211. dwRetCode = AfpServerIOCtrl( &AfpSrp );
  212. if (dwRetCode != ERROR_PATH_NOT_FOUND)
  213. {
  214. break;
  215. }
  216. Sleep( 2000);
  217. } while ( ++dwRetryCount < 4 );
  218. LocalFree( pAfpFinderInfoSR );
  219. }
  220. return( dwRetCode );
  221. }
  222. DWORD
  223. CopyStream(
  224. IN HANDLE hSrc,
  225. IN HANDLE hDst
  226. )
  227. {
  228. DWORD bytesread, byteswritten, Status = NO_ERROR;
  229. BYTE Buffer[1024 * 16];
  230. do
  231. {
  232. bytesread = byteswritten = 0;
  233. // read from src, write to dst
  234. //
  235. if (ReadFile(hSrc, Buffer, sizeof(Buffer), &bytesread, NULL))
  236. {
  237. if (bytesread == 0)
  238. {
  239. break;
  240. }
  241. }
  242. else
  243. {
  244. Status = GetLastError();
  245. break;
  246. }
  247. if (!WriteFile(hDst, Buffer, bytesread, &byteswritten, NULL))
  248. {
  249. Status = GetLastError();
  250. break;
  251. }
  252. } while (TRUE);
  253. return(Status);
  254. }
  255. BOOL
  256. IsTargetNTFS(
  257. IN LPWSTR lpwsPath
  258. )
  259. {
  260. WCHAR wchDrive[5];
  261. DWORD dwMaxCompSize;
  262. DWORD dwFlags;
  263. WCHAR wchFileSystem[10];
  264. // Get the drive letter, : and backslash
  265. //
  266. ZeroMemory( wchDrive, sizeof( wchDrive ) );
  267. STRNCPY( wchDrive, lpwsPath, 3 );
  268. if ( !( GetVolumeInformation( (LPWSTR)wchDrive,
  269. NULL,
  270. 0,
  271. NULL,
  272. &dwMaxCompSize,
  273. &dwFlags,
  274. (LPWSTR)wchFileSystem,
  275. sizeof( wchFileSystem ) ) ) ){
  276. return( FALSE );
  277. }
  278. if ( STRICMP( wchFileSystem, TEXT("NTFS") ) == 0 )
  279. return( TRUE );
  280. else
  281. return( FALSE );
  282. }