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.

894 lines
23 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: volume.c
  7. //
  8. // Description: This module contains support routines for the volume
  9. // category API's for the AFP server service
  10. //
  11. // History:
  12. // June 11,1992. NarenG Created original version.
  13. //
  14. #include "afpsvcp.h"
  15. static HANDLE hmutexInvalidVolume;
  16. // Invalid volume structure
  17. //
  18. typedef struct _AFP_BADVOLUME {
  19. LPWSTR lpwsName;
  20. LPWSTR lpwsPath;
  21. DWORD cbVariableData; // Number of bytes of name+path.
  22. struct _AFP_BADVOLUME * Next;
  23. } AFP_BADVOLUME, * PAFP_BADVOLUME;
  24. // Singly linked list of invalid volumes
  25. //
  26. typedef struct _AFP_INVALID_VOLUMES {
  27. DWORD cbTotalData;
  28. PAFP_BADVOLUME Head;
  29. } AFP_INVALID_VOLUMES;
  30. static AFP_INVALID_VOLUMES InvalidVolumeList;
  31. //**
  32. //
  33. // Call: AfpAdminrVolumeEnum
  34. //
  35. // Returns: NO_ERROR
  36. // ERROR_ACCESS_DENIED
  37. // non-zero returns from AfpServerIOCtrlGetInfo
  38. //
  39. // Description: This routine communicates with the AFP FSD to implement
  40. // the AfpAdminrVolumeEnum function.
  41. //
  42. DWORD
  43. AfpAdminrVolumeEnum(
  44. IN AFP_SERVER_HANDLE hServer,
  45. IN OUT PVOLUME_INFO_CONTAINER pInfoStruct,
  46. IN DWORD dwPreferedMaximumLength,
  47. OUT LPDWORD lpdwTotalEntries,
  48. IN OUT LPDWORD lpdwResumeHandle OPTIONAL
  49. )
  50. {
  51. AFP_REQUEST_PACKET AfpSrp;
  52. DWORD dwRetCode=0;
  53. DWORD dwAccessStatus=0;
  54. // Check if caller has access
  55. //
  56. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  57. {
  58. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeEnum, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  59. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS,
  60. 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE );
  61. return( ERROR_ACCESS_DENIED );
  62. }
  63. if ( dwAccessStatus )
  64. {
  65. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeEnum, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  66. return( ERROR_ACCESS_DENIED );
  67. }
  68. // Set up request packet and make IOCTL to the FSD
  69. //
  70. AfpSrp.dwRequestCode = OP_VOLUME_ENUM;
  71. AfpSrp.dwApiType = AFP_API_TYPE_ENUM;
  72. AfpSrp.Type.Enum.cbOutputBufSize = dwPreferedMaximumLength;
  73. // If resume handle was not passed then we set it to zero, cause caller
  74. // wants all information starting from the beginning.
  75. //
  76. if ( lpdwResumeHandle )
  77. AfpSrp.Type.Enum.EnumRequestPkt.erqp_Index = *lpdwResumeHandle;
  78. else
  79. AfpSrp.Type.Enum.EnumRequestPkt.erqp_Index = 0;
  80. dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp );
  81. if ( dwRetCode != ERROR_MORE_DATA && dwRetCode != NO_ERROR )
  82. return( dwRetCode );
  83. *lpdwTotalEntries = AfpSrp.Type.Enum.dwTotalAvail;
  84. pInfoStruct->pBuffer =(PAFP_VOLUME_INFO)(AfpSrp.Type.Enum.pOutputBuf);
  85. pInfoStruct->dwEntriesRead = AfpSrp.Type.Enum.dwEntriesRead;
  86. if ( lpdwResumeHandle )
  87. *lpdwResumeHandle = AfpSrp.Type.Enum.EnumRequestPkt.erqp_Index;
  88. // Convert all offsets to pointers
  89. //
  90. AfpBufOffsetToPointer( (LPBYTE)(pInfoStruct->pBuffer),
  91. pInfoStruct->dwEntriesRead,
  92. AFP_VOLUME_STRUCT );
  93. return( dwRetCode );
  94. }
  95. //**
  96. //
  97. // Call: AfpAdminrVolumeSetInfo
  98. //
  99. // Returns: NO_ERROR
  100. // ERROR_ACCESS_DENIED
  101. // non-zero returns from AfpServerIOCtrl
  102. //
  103. // Description: This routine communicates with the AFP FSD to implement
  104. // the AfpAdminVolumeSetInfo function.
  105. //
  106. DWORD
  107. AfpAdminrVolumeSetInfo(
  108. IN AFP_SERVER_HANDLE hServer,
  109. IN PAFP_VOLUME_INFO pAfpVolumeInfo,
  110. IN DWORD dwParmNum
  111. )
  112. {
  113. AFP_REQUEST_PACKET AfpSrp;
  114. DWORD dwRetCode=0;
  115. LPBYTE pAfpVolumeInfoSR = NULL;
  116. DWORD cbAfpVolumeInfoSRSize;
  117. DWORD dwAccessStatus=0;
  118. // Check if caller has access
  119. //
  120. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  121. {
  122. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeSetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  123. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  124. dwRetCode, EVENTLOG_ERROR_TYPE );
  125. return( ERROR_ACCESS_DENIED );
  126. }
  127. if ( dwAccessStatus )
  128. {
  129. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeSetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  130. return( ERROR_ACCESS_DENIED );
  131. }
  132. // MUTEX start
  133. //
  134. WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
  135. // This loop is used to allow break's instead of goto's to be used
  136. // on an error condition.
  137. //
  138. do {
  139. dwRetCode = NO_ERROR;
  140. // Make this buffer self-relative.
  141. //
  142. if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)pAfpVolumeInfo,
  143. sizeof(SETINFOREQPKT),
  144. AFP_VOLUME_STRUCT,
  145. &pAfpVolumeInfoSR,
  146. &cbAfpVolumeInfoSRSize ))
  147. break;
  148. // Make IOCTL to set info
  149. //
  150. AfpSrp.dwRequestCode = OP_VOLUME_SET_INFO;
  151. AfpSrp.dwApiType = AFP_API_TYPE_SETINFO;
  152. AfpSrp.Type.SetInfo.pInputBuf = pAfpVolumeInfoSR;
  153. AfpSrp.Type.SetInfo.cbInputBufSize = cbAfpVolumeInfoSRSize;
  154. AfpSrp.Type.SetInfo.dwParmNum = dwParmNum;
  155. if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) )
  156. break;
  157. // Now IOCTL the FSD to get information to set in the registry
  158. // The input buffer for a GetInfo type call should point to a volume
  159. // structure with the volume name filled in. Since we already have
  160. // this from the previos SetInfo call, we use the same buffer with
  161. // the pointer advances by sizeof(SETINFOREQPKT) bytes.
  162. //
  163. AfpSrp.dwRequestCode = OP_VOLUME_GET_INFO;
  164. AfpSrp.dwApiType = AFP_API_TYPE_GETINFO;
  165. AfpSrp.Type.GetInfo.pInputBuf = pAfpVolumeInfoSR +
  166. sizeof(SETINFOREQPKT);
  167. AfpSrp.Type.GetInfo.cbInputBufSize = cbAfpVolumeInfoSRSize -
  168. sizeof(SETINFOREQPKT);
  169. if ( dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp ) )
  170. break;
  171. // Update the registry if the IOCTL was successful
  172. //
  173. AfpBufOffsetToPointer( AfpSrp.Type.GetInfo.pOutputBuf,
  174. 1,
  175. AFP_VOLUME_STRUCT
  176. );
  177. dwRetCode = AfpRegVolumeSetInfo( AfpSrp.Type.GetInfo.pOutputBuf );
  178. LocalFree( AfpSrp.Type.GetInfo.pOutputBuf );
  179. } while( FALSE );
  180. // MUTEX end
  181. //
  182. ReleaseMutex( AfpGlobals.hmutexVolume );
  183. if ( pAfpVolumeInfoSR )
  184. LocalFree( pAfpVolumeInfoSR );
  185. return( dwRetCode );
  186. }
  187. //**
  188. //
  189. // Call: AfpAdminrVolumeDelete
  190. //
  191. // Returns: NO_ERROR
  192. // ERROR_ACCESS_DENIED
  193. // non-zero returns from AfpServerIOCtrl
  194. //
  195. // Description: This routine communicates with the AFP FSD to implement
  196. // the AfpAdminVolumeDelete function.
  197. //
  198. DWORD
  199. AfpAdminrVolumeDelete(
  200. IN AFP_SERVER_HANDLE hServer,
  201. IN LPWSTR lpwsVolumeName
  202. )
  203. {
  204. AFP_REQUEST_PACKET AfpSrp;
  205. PAFP_VOLUME_INFO pAfpVolumeInfoSR;
  206. AFP_VOLUME_INFO AfpVolumeInfo;
  207. DWORD cbAfpVolumeInfoSRSize;
  208. DWORD dwRetCode=0;
  209. DWORD dwAccessStatus=0;
  210. // Check if caller has access
  211. //
  212. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  213. {
  214. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeDelete, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  215. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  216. dwRetCode, EVENTLOG_ERROR_TYPE );
  217. return( ERROR_ACCESS_DENIED );
  218. }
  219. if ( dwAccessStatus )
  220. {
  221. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeDelete, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  222. return( ERROR_ACCESS_DENIED );
  223. }
  224. // Delete FSD request expects a AFP_VOLUME_INFO structure with only
  225. // the volume name field filled in.
  226. //
  227. AfpVolumeInfo.afpvol_name = lpwsVolumeName;
  228. AfpVolumeInfo.afpvol_password = NULL;
  229. AfpVolumeInfo.afpvol_path = NULL;
  230. // MUTEX start
  231. //
  232. WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
  233. // This loop is used to allow break's instead of goto's to be used
  234. // on an error condition.
  235. //
  236. do {
  237. dwRetCode = NO_ERROR;
  238. // Make this buffer self-relative.
  239. //
  240. if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)&AfpVolumeInfo,
  241. 0,
  242. AFP_VOLUME_STRUCT,
  243. (LPBYTE*)&pAfpVolumeInfoSR,
  244. &cbAfpVolumeInfoSRSize ) )
  245. break;
  246. // IOCTL the FSD to delete the volume
  247. //
  248. AfpSrp.dwRequestCode = OP_VOLUME_DELETE;
  249. AfpSrp.dwApiType = AFP_API_TYPE_DELETE;
  250. AfpSrp.Type.Delete.pInputBuf = pAfpVolumeInfoSR;
  251. AfpSrp.Type.Delete.cbInputBufSize = cbAfpVolumeInfoSRSize;
  252. dwRetCode = AfpServerIOCtrl( &AfpSrp );
  253. LocalFree( pAfpVolumeInfoSR );
  254. if ( dwRetCode )
  255. break;
  256. // Update the registry if the IOCTL was successful
  257. //
  258. dwRetCode = AfpRegVolumeDelete( lpwsVolumeName );
  259. } while( FALSE );
  260. // MUTEX end
  261. //
  262. ReleaseMutex( AfpGlobals.hmutexVolume );
  263. return( dwRetCode );
  264. }
  265. //**
  266. //
  267. // Call: AfpAdminrVolumeAdd
  268. //
  269. // Returns: NO_ERROR
  270. // ERROR_ACCESS_DENIED
  271. // non-zero returns from AfpServerIOCtrl
  272. //
  273. // Description: This routine communicates with the AFP FSD to implement
  274. // the AfpAdminVolumeAdd function.
  275. //
  276. DWORD
  277. AfpAdminrVolumeAdd(
  278. IN AFP_SERVER_HANDLE hServer,
  279. IN PAFP_VOLUME_INFO pAfpVolumeInfo
  280. )
  281. {
  282. AFP_REQUEST_PACKET AfpSrp;
  283. DWORD dwRetCode=0, dwLastDstCharIndex = 0;
  284. PAFP_VOLUME_INFO pAfpVolumeInfoSR = NULL;
  285. DWORD cbAfpVolumeInfoSRSize;
  286. DWORD dwAccessStatus=0;
  287. BOOL fCopiedIcon = FALSE;
  288. WCHAR wchSrcIconPath[MAX_PATH];
  289. WCHAR wchDstIconPath[MAX_PATH + AFPSERVER_VOLUME_ICON_FILE_SIZE + 1 + (sizeof(AFPSERVER_RESOURCE_STREAM)/sizeof(WCHAR))];
  290. WCHAR wchServerIconFile[AFPSERVER_VOLUME_ICON_FILE_SIZE] = AFPSERVER_VOLUME_ICON_FILE;
  291. // Check if caller has access
  292. //
  293. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  294. {
  295. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  296. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0,
  297. NULL, dwRetCode, EVENTLOG_ERROR_TYPE );
  298. return( ERROR_ACCESS_DENIED );
  299. }
  300. if ( dwAccessStatus )
  301. {
  302. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  303. return( ERROR_ACCESS_DENIED );
  304. }
  305. if ( pAfpVolumeInfo == NULL)
  306. {
  307. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, pAfpVolumeInfo == NULL\n"));
  308. return( ERROR_INVALID_DATA );
  309. }
  310. // MUTEX start
  311. //
  312. WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
  313. // This loop is used to allow break's instead of goto's to be used
  314. // on an error condition.
  315. //
  316. do {
  317. // Copy the server icon to the volume root
  318. //
  319. // Construct a path to the NTSFM volume custom icon
  320. //
  321. if ( GetSystemDirectory( wchSrcIconPath, MAX_PATH ) )
  322. {
  323. wcscat( wchSrcIconPath, AFP_DEF_VOLICON_SRCNAME );
  324. if ( pAfpVolumeInfo->afpvol_path == NULL )
  325. {
  326. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, pAfpVolumeInfo->afpvol_path == NULL\n"));
  327. dwRetCode = ERROR_INVALID_DATA;
  328. break;
  329. }
  330. // Construct a path to the destination volume "Icon<0D>" file
  331. //
  332. wcscpy( wchDstIconPath, pAfpVolumeInfo->afpvol_path );
  333. if ( wcslen(wchDstIconPath) == 0 )
  334. {
  335. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, wcslen(wchDstIconPath) == 0\n"));
  336. dwRetCode = ERROR_INVALID_DATA;
  337. break;
  338. }
  339. if (wchDstIconPath[wcslen(wchDstIconPath) - 1] != TEXT('\\'))
  340. {
  341. wcscat( wchDstIconPath, TEXT("\\") );
  342. }
  343. wcscat( wchDstIconPath, wchServerIconFile );
  344. // Keep track of end of name without the resource fork tacked on
  345. //
  346. dwLastDstCharIndex = wcslen(wchDstIconPath);
  347. wcscat( wchDstIconPath, AFPSERVER_RESOURCE_STREAM );
  348. // Copy the icon file to the root of the volume (do not overwrite)
  349. //
  350. if ((fCopiedIcon = CopyFile( wchSrcIconPath, wchDstIconPath, TRUE )) ||
  351. (GetLastError() == ERROR_FILE_EXISTS))
  352. {
  353. pAfpVolumeInfo->afpvol_props_mask |= AFP_VOLUME_HAS_CUSTOM_ICON;
  354. // Make sure the file is hidden
  355. SetFileAttributes( wchDstIconPath,
  356. FILE_ATTRIBUTE_HIDDEN |
  357. FILE_ATTRIBUTE_ARCHIVE );
  358. }
  359. }
  360. else
  361. {
  362. dwRetCode = GetLastError ();
  363. break;
  364. }
  365. // Make this buffer self-relative.
  366. //
  367. if ( dwRetCode = AfpBufMakeFSDRequest( (LPBYTE)pAfpVolumeInfo,
  368. 0,
  369. AFP_VOLUME_STRUCT,
  370. (LPBYTE*)&pAfpVolumeInfoSR,
  371. &cbAfpVolumeInfoSRSize ) )
  372. break;
  373. // IOCTL the FSD to add the volume
  374. //
  375. AfpSrp.dwRequestCode = OP_VOLUME_ADD;
  376. AfpSrp.dwApiType = AFP_API_TYPE_ADD;
  377. AfpSrp.Type.Add.pInputBuf = pAfpVolumeInfoSR;
  378. AfpSrp.Type.Add.cbInputBufSize = cbAfpVolumeInfoSRSize;
  379. dwRetCode = AfpServerIOCtrl( &AfpSrp );
  380. // Don't allow icon bit to be written to the registry if it was set
  381. pAfpVolumeInfo->afpvol_props_mask &= ~AFP_VOLUME_HAS_CUSTOM_ICON;
  382. if ( dwRetCode )
  383. {
  384. // Delete the icon file we just copied if the volume add failed
  385. //
  386. if ( fCopiedIcon )
  387. {
  388. // Truncate the resource fork name so we delete the whole file
  389. wchDstIconPath[dwLastDstCharIndex] = 0;
  390. DeleteFile( wchDstIconPath );
  391. }
  392. break;
  393. }
  394. // Update the registry if the IOCTL was successful
  395. //
  396. dwRetCode = AfpRegVolumeAdd( pAfpVolumeInfo );
  397. if ( dwRetCode )
  398. break;
  399. // Delete this volume if it exists in the invalid volume list
  400. //
  401. AfpDeleteInvalidVolume( pAfpVolumeInfo->afpvol_name );
  402. } while( FALSE );
  403. // MUTEX end
  404. //
  405. ReleaseMutex( AfpGlobals.hmutexVolume );
  406. if ( pAfpVolumeInfoSR != NULL )
  407. LocalFree( pAfpVolumeInfoSR );
  408. return( dwRetCode );
  409. }
  410. //**
  411. //
  412. // Call: AfpAdminrVolumeGetInfo
  413. //
  414. // Returns: NO_ERROR
  415. // ERROR_ACCESS_DENIED
  416. // non-zero returns from AfpServerIOCtrlGetInfo
  417. //
  418. // Description: This routine communicates with the AFP FSD to implement
  419. // the AfpAdminVolumeGetInfo function.
  420. //
  421. DWORD
  422. AfpAdminrVolumeGetInfo(
  423. IN AFP_SERVER_HANDLE hServer,
  424. IN LPWSTR lpwsVolumeName,
  425. OUT PAFP_VOLUME_INFO* ppAfpVolumeInfo
  426. )
  427. {
  428. AFP_REQUEST_PACKET AfpSrp;
  429. PAFP_VOLUME_INFO pAfpVolumeInfoSR;
  430. AFP_VOLUME_INFO AfpVolumeInfo;
  431. DWORD cbAfpVolumeInfoSRSize;
  432. DWORD dwRetCode=0;
  433. DWORD dwAccessStatus=0;
  434. // Check if caller has access
  435. //
  436. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  437. {
  438. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeGetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  439. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  440. dwRetCode, EVENTLOG_ERROR_TYPE );
  441. return( ERROR_ACCESS_DENIED );
  442. }
  443. if ( dwAccessStatus )
  444. {
  445. AFP_PRINT(( "SFMSVC: AfpAdminrVolumeGetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  446. return( ERROR_ACCESS_DENIED );
  447. }
  448. // MUTEX start
  449. //
  450. WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
  451. // This loop is used to allow break's instead of goto's to be used
  452. // on an error condition.
  453. //
  454. do {
  455. dwRetCode = NO_ERROR;
  456. // Get info FSD request expects a AFP_VOLUME_INFO structure with only
  457. // the volume name field filled in.
  458. //
  459. AfpVolumeInfo.afpvol_name = lpwsVolumeName;
  460. AfpVolumeInfo.afpvol_password = NULL;
  461. AfpVolumeInfo.afpvol_path = NULL;
  462. // Make this buffer self-relative.
  463. //
  464. if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)&AfpVolumeInfo,
  465. 0,
  466. AFP_VOLUME_STRUCT,
  467. (LPBYTE*)&pAfpVolumeInfoSR,
  468. &cbAfpVolumeInfoSRSize ) )
  469. break;
  470. AfpSrp.dwRequestCode = OP_VOLUME_GET_INFO;
  471. AfpSrp.dwApiType = AFP_API_TYPE_GETINFO;
  472. AfpSrp.Type.GetInfo.pInputBuf = pAfpVolumeInfoSR;
  473. AfpSrp.Type.GetInfo.cbInputBufSize = cbAfpVolumeInfoSRSize;
  474. dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp );
  475. if ( dwRetCode != ERROR_MORE_DATA && dwRetCode != NO_ERROR )
  476. break;
  477. LocalFree( pAfpVolumeInfoSR );
  478. *ppAfpVolumeInfo = AfpSrp.Type.GetInfo.pOutputBuf;
  479. // Convert all offsets to pointers
  480. //
  481. AfpBufOffsetToPointer( (LPBYTE)*ppAfpVolumeInfo, 1, AFP_VOLUME_STRUCT);
  482. } while( FALSE );
  483. // MUTEX end
  484. //
  485. ReleaseMutex( AfpGlobals.hmutexVolume );
  486. return( dwRetCode );
  487. }
  488. //**
  489. //
  490. // Call: AfpAdminrInvalidVolumeEnum
  491. //
  492. // Returns: NO_ERROR
  493. // ERROR_ACCESS_DENIED
  494. //
  495. // Description: This routine will return a list of all invalid volumes. This
  496. // List is stored in a cache that is local to this module.
  497. //
  498. DWORD
  499. AfpAdminrInvalidVolumeEnum(
  500. IN AFP_SERVER_HANDLE hServer,
  501. IN OUT PVOLUME_INFO_CONTAINER pInfoStruct
  502. )
  503. {
  504. DWORD dwRetCode=0;
  505. DWORD dwAccessStatus=0;
  506. PAFP_VOLUME_INFO pOutputBuf;
  507. PAFP_VOLUME_INFO pOutputWalker;
  508. WCHAR * pwchVariableData;
  509. PAFP_BADVOLUME pAfpBadVolWalker;
  510. // Check if caller has access
  511. //
  512. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  513. {
  514. AFP_PRINT(( "SFMSVC: AfpAdminrInvalidVolumeEnum, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  515. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  516. dwRetCode, EVENTLOG_ERROR_TYPE );
  517. return( ERROR_ACCESS_DENIED );
  518. }
  519. if ( dwAccessStatus )
  520. {
  521. AFP_PRINT(( "SFMSVC: AfpAdminrInvalidVolumeEnum, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  522. return( ERROR_ACCESS_DENIED );
  523. }
  524. // MUTEX start
  525. //
  526. WaitForSingleObject( hmutexInvalidVolume, INFINITE );
  527. // Allocate enough space to hold all the information.
  528. //
  529. pOutputBuf = MIDL_user_allocate( InvalidVolumeList.cbTotalData );
  530. if ( pOutputBuf == NULL ){
  531. ReleaseMutex( hmutexInvalidVolume );
  532. return( ERROR_NOT_ENOUGH_MEMORY );
  533. }
  534. ZeroMemory( pOutputBuf, InvalidVolumeList.cbTotalData );
  535. // Variable data begins from the end of the buffer.
  536. //
  537. pwchVariableData=(WCHAR*)((ULONG_PTR)pOutputBuf+InvalidVolumeList.cbTotalData);
  538. // Walk the list and create the array of volume structures
  539. //
  540. for( pAfpBadVolWalker = InvalidVolumeList.Head,
  541. pInfoStruct->dwEntriesRead = 0,
  542. pOutputWalker = pOutputBuf;
  543. pAfpBadVolWalker != NULL;
  544. pOutputWalker++,
  545. (pInfoStruct->dwEntriesRead)++,
  546. pAfpBadVolWalker = pAfpBadVolWalker->Next ) {
  547. pwchVariableData -= (STRLEN(pAfpBadVolWalker->lpwsName) + 1);
  548. STRCPY( (LPWSTR)pwchVariableData, pAfpBadVolWalker->lpwsName );
  549. pOutputWalker->afpvol_name = (LPWSTR)pwchVariableData;
  550. if ( pAfpBadVolWalker->lpwsPath != NULL ) {
  551. pwchVariableData -=( STRLEN(pAfpBadVolWalker->lpwsPath)+1 );
  552. STRCPY( (LPWSTR)pwchVariableData, pAfpBadVolWalker->lpwsPath );
  553. pOutputWalker->afpvol_path = (LPWSTR)pwchVariableData;
  554. }
  555. }
  556. // MUTEX end
  557. //
  558. ReleaseMutex( hmutexInvalidVolume );
  559. pInfoStruct->pBuffer = pOutputBuf;
  560. return( dwRetCode );
  561. }
  562. //**
  563. //
  564. // Call: AfpAdminrInvalidVolumeDelete
  565. //
  566. // Returns: NO_ERROR
  567. // ERROR_ACCESS_DENIED
  568. //
  569. // Description: This routine will remove an invalid volume from the registry
  570. // and the list of invalid volumes.
  571. //
  572. DWORD
  573. AfpAdminrInvalidVolumeDelete(
  574. IN AFP_SERVER_HANDLE hServer,
  575. IN LPWSTR lpwsVolumeName
  576. )
  577. {
  578. DWORD dwRetCode=0;
  579. DWORD dwAccessStatus=0;
  580. // Check if caller has access
  581. //
  582. if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
  583. {
  584. AFP_PRINT(( "SFMSVC: AfpAdminrInvalidVolumeDelete, AfpSecObjAccessCheck failed %ld\n",dwRetCode));
  585. AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL,
  586. dwRetCode, EVENTLOG_ERROR_TYPE );
  587. return( ERROR_ACCESS_DENIED );
  588. }
  589. if ( dwAccessStatus )
  590. {
  591. AFP_PRINT(( "SFMSVC: AfpAdminrInvalidVolumeDelete, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
  592. return( ERROR_ACCESS_DENIED );
  593. }
  594. // Remove this volume from the registry
  595. //
  596. if ( dwRetCode = AfpRegVolumeDelete( lpwsVolumeName ) ) {
  597. if ( dwRetCode == ERROR_FILE_NOT_FOUND )
  598. dwRetCode = (DWORD)AFPERR_VolumeNonExist;
  599. }
  600. // MUTEX start
  601. //
  602. WaitForSingleObject( hmutexInvalidVolume, INFINITE );
  603. AfpDeleteInvalidVolume( lpwsVolumeName );
  604. // MUTEX end
  605. //
  606. ReleaseMutex( hmutexInvalidVolume );
  607. return( dwRetCode );
  608. }
  609. //**
  610. //
  611. // Call: AfpAddInvalidVolume
  612. //
  613. // Returns: none
  614. //
  615. // Description: Will add a volume structure to a sigly linked list of volumes.
  616. //
  617. VOID
  618. AfpAddInvalidVolume(
  619. IN LPWSTR lpwsName,
  620. IN LPWSTR lpwsPath
  621. )
  622. {
  623. DWORD dwRetCode = NO_ERROR;
  624. WCHAR* pwchVariableData = NULL;
  625. PAFP_BADVOLUME pAfpVolumeInfo = NULL;
  626. DWORD cbVariableData;
  627. // MUTEX start
  628. //
  629. WaitForSingleObject( hmutexInvalidVolume, INFINITE );
  630. do {
  631. cbVariableData = (STRLEN(lpwsName)+1) * sizeof(WCHAR);
  632. if ( lpwsPath != NULL )
  633. cbVariableData += ( (STRLEN(lpwsPath)+1)*sizeof(WCHAR) );
  634. pwchVariableData = (WCHAR*)LocalAlloc( LPTR, cbVariableData );
  635. if ( pwchVariableData == NULL ) {
  636. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  637. break;
  638. }
  639. pAfpVolumeInfo = (PAFP_BADVOLUME)LocalAlloc( LPTR,
  640. sizeof(AFP_BADVOLUME));
  641. if ( pAfpVolumeInfo == NULL ) {
  642. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  643. break;
  644. }
  645. // Add the volume strucutre
  646. //
  647. pAfpVolumeInfo->Next = InvalidVolumeList.Head;
  648. InvalidVolumeList.Head = pAfpVolumeInfo;
  649. // Add the name and the path
  650. //
  651. STRCPY( (LPWSTR)pwchVariableData, lpwsName );
  652. pAfpVolumeInfo->lpwsName = (LPWSTR)pwchVariableData;
  653. if ( lpwsPath != NULL ) {
  654. pwchVariableData += ( STRLEN( lpwsName ) + 1);
  655. STRCPY( (LPWSTR)pwchVariableData, lpwsPath );
  656. pAfpVolumeInfo->lpwsPath = (LPWSTR)pwchVariableData;
  657. }
  658. pAfpVolumeInfo->cbVariableData = cbVariableData;
  659. InvalidVolumeList.cbTotalData += ( sizeof( AFP_VOLUME_INFO ) +
  660. cbVariableData );
  661. } while( FALSE );
  662. if ( dwRetCode != NO_ERROR ) {
  663. if ( pAfpVolumeInfo != NULL )
  664. LocalFree( pAfpVolumeInfo );
  665. if ( pwchVariableData != NULL ) {
  666. LocalFree( pwchVariableData );
  667. }
  668. }
  669. // MUTEX end
  670. //
  671. ReleaseMutex( hmutexInvalidVolume );
  672. }
  673. //**
  674. //
  675. // Call: AfpDeleteInvalidVolume
  676. //
  677. // Returns: none
  678. //
  679. // Description: Will delete a volume structure from the list of invalid
  680. // volumes, if it is found.
  681. //
  682. VOID
  683. AfpDeleteInvalidVolume(
  684. IN LPWSTR lpwsVolumeName
  685. )
  686. {
  687. PAFP_BADVOLUME pTmp;
  688. PAFP_BADVOLUME pBadVolWalker;
  689. // Walk the list and delete the volume structure
  690. //
  691. if ( InvalidVolumeList.Head != NULL ) {
  692. if ( STRICMP( InvalidVolumeList.Head->lpwsName, lpwsVolumeName ) == 0 ){
  693. pTmp = InvalidVolumeList.Head;
  694. InvalidVolumeList.cbTotalData -= ( sizeof( AFP_VOLUME_INFO )
  695. + pTmp->cbVariableData );
  696. InvalidVolumeList.Head = pTmp->Next;
  697. LocalFree( pTmp->lpwsName );
  698. LocalFree( pTmp );
  699. }
  700. else {
  701. for( pBadVolWalker = InvalidVolumeList.Head;
  702. pBadVolWalker->Next != NULL;
  703. pBadVolWalker = pBadVolWalker->Next ) {
  704. if ( STRICMP( pBadVolWalker->Next->lpwsName, lpwsVolumeName )
  705. == 0 ) {
  706. pTmp = pBadVolWalker->Next;
  707. InvalidVolumeList.cbTotalData -= ( sizeof( AFP_VOLUME_INFO )
  708. + pTmp->cbVariableData );
  709. pBadVolWalker->Next = pTmp->Next;
  710. LocalFree( pTmp->lpwsName );
  711. LocalFree( pTmp);
  712. break;
  713. }
  714. }
  715. }
  716. }
  717. }