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.

4581 lines
146 KiB

  1. /*++
  2. Copyright (c) 1992-2001 Microsoft Corporation
  3. Module Name:
  4. smbshare.c
  5. Abstract:
  6. Resource DLL for File Shares.
  7. Author:
  8. Rod Gamache (rodga) 8-Jan-1996
  9. Revision History:
  10. --*/
  11. #define UNICODE 1
  12. #include "clusres.h"
  13. #include "clusrtl.h"
  14. #include "lm.h"
  15. #include "lmerr.h"
  16. #include "lmshare.h"
  17. #include <dfsfsctl.h>
  18. #include <srvfsctl.h>
  19. #include <lmdfs.h>
  20. #include <validc.h>
  21. #include <strsafe.h>
  22. #define LOG_CURRENT_MODULE LOG_MODULE_SMB
  23. #define SMB_SVCNAME TEXT("LanmanServer")
  24. #define DFS_SVCNAME TEXT("Dfs")
  25. #define MAX_RETRIES 20
  26. #define DBG_PRINT printf
  27. #define PARAM_KEYNAME__PARAMETERS CLUSREG_KEYNAME_PARAMETERS
  28. #define PARAM_NAME__SHARENAME CLUSREG_NAME_FILESHR_SHARE_NAME
  29. #define PARAM_NAME__PATH CLUSREG_NAME_FILESHR_PATH
  30. #define PARAM_NAME__REMARK CLUSREG_NAME_FILESHR_REMARK
  31. #define PARAM_NAME__MAXUSERS CLUSREG_NAME_FILESHR_MAX_USERS
  32. #define PARAM_NAME__SECURITY CLUSREG_NAME_FILESHR_SECURITY
  33. #define PARAM_NAME__SD CLUSREG_NAME_FILESHR_SD
  34. #define PARAM_NAME__SHARESUBDIRS CLUSREG_NAME_FILESHR_SHARE_SUBDIRS
  35. #define PARAM_NAME__HIDESUBDIRSHARES CLUSREG_NAME_FILESHR_HIDE_SUBDIR_SHARES
  36. #define PARAM_NAME__DFSROOT CLUSREG_NAME_FILESHR_IS_DFS_ROOT
  37. #define PARAM_NAME__CSCCACHE CLUSREG_NAME_FILESHR_CSC_CACHE
  38. #define PARAM_MIN__MAXUSERS 0
  39. #define PARAM_MAX__MAXUSERS ((DWORD)-1)
  40. #define PARAM_DEFAULT__MAXUSERS ((DWORD)-1)
  41. #define FREE_SECURITY_INFO() \
  42. LocalFree( params.Security ); \
  43. params.Security = NULL; \
  44. params.SecuritySize = 0; \
  45. LocalFree( params.SecurityDescriptor ); \
  46. params.SecurityDescriptor = NULL; \
  47. params.SecurityDescriptorSize = 0
  48. #define SMBSHARE_EXTRA_LEN 10
  49. typedef struct _SUBDIR_SHARE_INFO {
  50. LIST_ENTRY ListEntry;
  51. WCHAR ShareName [NNLEN+1];
  52. }SUBDIR_SHARE_INFO,*PSUBDIR_SHARE_INFO;
  53. typedef struct _SHARE_PARAMS {
  54. LPWSTR ShareName;
  55. LPWSTR Path;
  56. LPWSTR Remark;
  57. ULONG MaxUsers;
  58. PUCHAR Security;
  59. ULONG SecuritySize;
  60. ULONG ShareSubDirs;
  61. ULONG HideSubDirShares;
  62. ULONG DfsRoot;
  63. ULONG CSCCache;
  64. PUCHAR SecurityDescriptor;
  65. ULONG SecurityDescriptorSize;
  66. } SHARE_PARAMS, *PSHARE_PARAMS;
  67. typedef struct _SHARE_RESOURCE {
  68. RESID ResId; // for validation
  69. SHARE_PARAMS Params;
  70. HKEY ResourceKey;
  71. HKEY ParametersKey;
  72. RESOURCE_HANDLE ResourceHandle;
  73. WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
  74. CLUS_WORKER PendingThread;
  75. CLUSTER_RESOURCE_STATE State;
  76. LIST_ENTRY SubDirList;
  77. HRESOURCE hResource;
  78. CLUS_WORKER NotifyWorker;
  79. HANDLE NotifyHandle;
  80. BOOL bDfsRootNeedsMonitoring;
  81. WCHAR szDependentNetworkName[MAX_COMPUTERNAME_LENGTH+1];
  82. } SHARE_RESOURCE, *PSHARE_RESOURCE;
  83. typedef struct _SHARE_TYPE_LIST {
  84. PWSTR Name;
  85. ULONG Type;
  86. } SHARE_TYPE_LIST, *PSHARE_TYPE_LIST;
  87. typedef struct SHARE_ENUM_CONTEXT {
  88. PSHARE_RESOURCE pResourceEntry;
  89. PSHARE_PARAMS pParams;
  90. } SHARE_ENUM_CONTEXT, *PSHARE_ENUM_CONTEXT;
  91. //
  92. // Global data.
  93. //
  94. CRITICAL_SECTION SmbShareLock;
  95. // Log Event Routine
  96. #define g_LogEvent ClusResLogEvent
  97. #define g_SetResourceStatus ClusResSetResourceStatus
  98. // Forward reference to our RESAPI function table.
  99. extern CLRES_FUNCTION_TABLE SmbShareFunctionTable;
  100. //
  101. // SmbShare resource read-write private properties
  102. //
  103. RESUTIL_PROPERTY_ITEM
  104. SmbShareResourcePrivateProperties[] = {
  105. { PARAM_NAME__SHARENAME, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_REQUIRED, FIELD_OFFSET(SHARE_PARAMS,ShareName) },
  106. { PARAM_NAME__PATH, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_REQUIRED, FIELD_OFFSET(SHARE_PARAMS,Path) },
  107. { PARAM_NAME__REMARK, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, 0, FIELD_OFFSET(SHARE_PARAMS,Remark) },
  108. { PARAM_NAME__MAXUSERS, NULL, CLUSPROP_FORMAT_DWORD, PARAM_DEFAULT__MAXUSERS, PARAM_MIN__MAXUSERS, PARAM_MAX__MAXUSERS, 0, FIELD_OFFSET(SHARE_PARAMS,MaxUsers) },
  109. { PARAM_NAME__SECURITY, NULL, CLUSPROP_FORMAT_BINARY, 0, 0, 0, 0, FIELD_OFFSET(SHARE_PARAMS,Security) },
  110. { PARAM_NAME__SHARESUBDIRS, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 1, 0, FIELD_OFFSET(SHARE_PARAMS,ShareSubDirs) },
  111. { PARAM_NAME__HIDESUBDIRSHARES, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 1, 0, FIELD_OFFSET(SHARE_PARAMS,HideSubDirShares) },
  112. { PARAM_NAME__DFSROOT, NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 1, 0, FIELD_OFFSET(SHARE_PARAMS, DfsRoot) },
  113. { PARAM_NAME__SD, NULL, CLUSPROP_FORMAT_BINARY, 0, 0, 0, 0, FIELD_OFFSET(SHARE_PARAMS,SecurityDescriptor) },
  114. { PARAM_NAME__CSCCACHE, NULL, CLUSPROP_FORMAT_DWORD, CSC_CACHE_MANUAL_REINT, CSC_CACHE_MANUAL_REINT, CSC_CACHE_NONE, 0, FIELD_OFFSET(SHARE_PARAMS,CSCCache) },
  115. { NULL, NULL, 0, 0, 0, 0 }
  116. };
  117. typedef struct _SMB_DEPEND_SETUP {
  118. DWORD Offset;
  119. CLUSPROP_SYNTAX Syntax;
  120. DWORD Length;
  121. PVOID Value;
  122. } SMB_DEPEND_SETUP, *PSMB_DEPEND_SETUP;
  123. typedef struct _SMB_DEPEND_DATA {
  124. #if 0
  125. CLUSPROP_RESOURCE_CLASS storageEntry;
  126. #endif
  127. CLUSPROP_SYNTAX endmark;
  128. } SMB_DEPEND_DATA, *PSMB_DEPEND_DATA;
  129. typedef struct _DFS_DEPEND_DATA {
  130. #if 0
  131. CLUSPROP_RESOURCE_CLASS storageEntry;
  132. #endif
  133. CLUSPROP_SZ_DECLARE( networkEntry, sizeof(CLUS_RESTYPE_NAME_NETNAME) / sizeof(WCHAR) );
  134. CLUSPROP_SYNTAX endmark;
  135. } DFS_DEPEND_DATA, *PDFS_DEPEND_DATA;
  136. // This table is for Smb Share dependencies only
  137. SMB_DEPEND_SETUP SmbDependSetup[] = {
  138. #if 0 // rodga - allow for dependency on a local disk
  139. { FIELD_OFFSET(SMB_DEPEND_DATA, storageEntry), CLUSPROP_SYNTAX_RESCLASS, sizeof(CLUSTER_RESOURCE_CLASS), (PVOID)CLUS_RESCLASS_STORAGE },
  140. #endif
  141. { 0, 0 }
  142. };
  143. // This table is for DFS Share dependencies only
  144. SMB_DEPEND_SETUP DfsDependSetup[] = {
  145. #if 0 // rodga - allow for dependency on a local disk
  146. { FIELD_OFFSET(DFS_DEPEND_DATA, storageEntry), CLUSPROP_SYNTAX_RESCLASS, sizeof(CLUSTER_RESOURCE_CLASS), (PVOID)CLUS_RESCLASS_STORAGE },
  147. #endif
  148. { FIELD_OFFSET(DFS_DEPEND_DATA, networkEntry), CLUSPROP_SYNTAX_NAME, sizeof(CLUS_RESTYPE_NAME_NETNAME), CLUS_RESTYPE_NAME_NETNAME },
  149. { 0, 0 }
  150. };
  151. BOOL g_fDfsServiceNeedsRecyling = FALSE;
  152. //
  153. // External references
  154. //
  155. BOOL
  156. SmbExamineSD(
  157. RESOURCE_HANDLE ResourceHandle,
  158. PSECURITY_DESCRIPTOR psdSD
  159. );
  160. //
  161. // Forward references
  162. //
  163. BOOL
  164. WINAPI
  165. SmbShareIsAlive(
  166. IN RESID Resource
  167. );
  168. DWORD
  169. SmbShareGetPrivateResProperties(
  170. IN OUT PSHARE_RESOURCE ResourceEntry,
  171. OUT PVOID OutBuffer,
  172. IN DWORD OutBufferSize,
  173. OUT LPDWORD BytesReturned
  174. );
  175. DWORD
  176. SmbShareValidatePrivateResProperties(
  177. IN OUT PSHARE_RESOURCE ResourceEntry,
  178. IN PVOID InBuffer,
  179. IN DWORD InBufferSize,
  180. OUT PSHARE_PARAMS Params
  181. );
  182. DWORD
  183. SmbShareSetPrivateResProperties(
  184. IN OUT PSHARE_RESOURCE ResourceEntry,
  185. IN PVOID InBuffer,
  186. IN DWORD InBufferSize
  187. );
  188. DWORD
  189. SmbpIsDfsRoot(
  190. IN PSHARE_RESOURCE ResourceEntry,
  191. OUT PBOOL pbIsDfsRoot
  192. );
  193. DWORD
  194. SmbpPrepareOnlineDfsRoot(
  195. IN PSHARE_RESOURCE ResourceEntry
  196. );
  197. DWORD
  198. SmbpCreateDfsRoot(
  199. IN PSHARE_RESOURCE pResourceEntry
  200. );
  201. DWORD
  202. SmbpDeleteDfsRoot(
  203. IN PSHARE_RESOURCE pResourceEntry
  204. );
  205. DWORD
  206. SmbpShareNotifyThread(
  207. IN PCLUS_WORKER pWorker,
  208. IN PSHARE_RESOURCE pResourceEntry
  209. );
  210. DWORD
  211. SmbpCheckForSubDirDeletion (
  212. IN PSHARE_RESOURCE pResourceEntry
  213. );
  214. DWORD
  215. SmbpCheckAndBringSubSharesOnline (
  216. IN PSHARE_RESOURCE pResourceEntry,
  217. IN BOOL IsCheckAllSubDirs,
  218. IN PRESOURCE_STATUS pResourceStatus,
  219. IN PCLUS_WORKER pWorker,
  220. OUT LPWSTR *pszRootDirOut
  221. );
  222. DWORD
  223. SmbpHandleDfsRoot(
  224. IN PSHARE_RESOURCE pResourceEntry,
  225. OUT PBOOL pbIsDfsRoot
  226. );
  227. DWORD
  228. SmbpResetDfs(
  229. IN PSHARE_RESOURCE pResourceEntry
  230. );
  231. DWORD
  232. SmbpValidateShareName(
  233. IN LPCWSTR lpszShareName
  234. );
  235. //
  236. // Private DFS APIs provided bu UDAYH - 4/26/2001
  237. //
  238. DWORD
  239. GetDfsRootMetadataLocation(
  240. LPWSTR RootName,
  241. LPWSTR *pMetadataNameLocation
  242. );
  243. VOID
  244. ReleaseDfsRootMetadataLocation(
  245. LPWSTR Buffer
  246. );
  247. DWORD
  248. SmbpRecycleDfsService(
  249. IN PSHARE_RESOURCE pResourceEntry
  250. );
  251. DWORD
  252. SmbpSetCacheFlags(
  253. IN PSHARE_RESOURCE ResourceEntry,
  254. IN LPWSTR ShareName
  255. )
  256. /*++
  257. Routine Description:
  258. Set the caching flags for the given resource entry.
  259. Arguments:
  260. ResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  261. ShareName - the name of the share to set cache flags for.
  262. Returns:
  263. ERROR_SUCCESS if successful.
  264. Win32 error code on failure.
  265. --*/
  266. {
  267. DWORD status;
  268. DWORD invalidParam;
  269. PSHARE_INFO_1005 shi1005;
  270. status = NetShareGetInfo( NULL,
  271. ShareName,
  272. 1005,
  273. (LPBYTE *)&shi1005 );
  274. if ( status != ERROR_SUCCESS ) {
  275. (g_LogEvent)(
  276. ResourceEntry->ResourceHandle,
  277. LOG_ERROR,
  278. L"SetCacheFlags, error getting CSC info on share '%1!ws!. Error %2!u!.\n",
  279. ShareName,
  280. status );
  281. goto exit;
  282. } else {
  283. shi1005->shi1005_flags &= ~CSC_MASK;
  284. shi1005->shi1005_flags |= (ResourceEntry->Params.CSCCache & CSC_MASK);
  285. status = NetShareSetInfo( NULL,
  286. ShareName,
  287. 1005,
  288. (LPBYTE)shi1005,
  289. &invalidParam );
  290. NetApiBufferFree((TCHAR FAR *)shi1005);
  291. if ( status != ERROR_SUCCESS ) {
  292. (g_LogEvent)(
  293. ResourceEntry->ResourceHandle,
  294. LOG_ERROR,
  295. L"SetCacheFlags, error setting CSC info on share '%1!ws!. Error %2!u!, property # %3!d!.\n",
  296. ShareName,
  297. status,
  298. invalidParam );
  299. }
  300. }
  301. exit:
  302. return(status);
  303. } // SmbpSetCacheFlags()
  304. BOOLEAN
  305. WINAPI
  306. SmbShareDllEntryPoint(
  307. IN HINSTANCE DllHandle,
  308. IN DWORD Reason,
  309. IN LPVOID Reserved
  310. )
  311. {
  312. switch( Reason ) {
  313. case DLL_PROCESS_ATTACH:
  314. InitializeCriticalSection( &SmbShareLock );
  315. break;
  316. case DLL_PROCESS_DETACH:
  317. DeleteCriticalSection( &SmbShareLock );
  318. break;
  319. default:
  320. break;
  321. }
  322. return(TRUE);
  323. } // SmbShareDllEntryPoint
  324. DWORD
  325. SmbpShareNotifyThread(
  326. IN PCLUS_WORKER pWorker,
  327. IN PSHARE_RESOURCE pResourceEntry
  328. )
  329. /*++
  330. Routine Description:
  331. Check whether any new subdirs have been added or deleted from
  332. under the root share.
  333. Arguments:
  334. pWorker - Supplies the worker structure.
  335. pResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  336. Returns:
  337. ERROR_SUCCESS if successful.
  338. Win32 error code on failure.
  339. --*/
  340. {
  341. DWORD status = ERROR_SUCCESS;
  342. LPWSTR pszRootDir;
  343. //
  344. // Chittur Subbaraman (chitturs) - 09/25/98
  345. //
  346. // This notification thread is activated once a
  347. // notification is received. This thread checks for any
  348. // new subdir additions or any subdir deletions. If it
  349. // finds such an occurrence, this thread adds the subdir to
  350. // or deletes the subdir from the root share. The two
  351. // Smbp functions this thread calls also checks
  352. // whether any termination command has arrived from the
  353. // offline thread. If such a command has arrived, this thread
  354. // terminates immediately, thus releasing the offline thread
  355. // from the infinite time wait.
  356. //
  357. SmbpCheckForSubDirDeletion( pResourceEntry );
  358. SmbpCheckAndBringSubSharesOnline( pResourceEntry,
  359. TRUE,
  360. NULL,
  361. &pResourceEntry->NotifyWorker,
  362. &pszRootDir );
  363. LocalFree ( pszRootDir );
  364. return(status);
  365. } // SmbShareNotify
  366. DWORD
  367. SmbpCheckForSubDirDeletion (
  368. IN PSHARE_RESOURCE pResourceEntry
  369. )
  370. /*++
  371. Routine Description:
  372. Check and remove any deleted subdirectory shares.
  373. Arguments:
  374. ResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  375. Returns:
  376. ERROR_SUCCESS if successful.
  377. Win32 error code on failure.
  378. --*/
  379. {
  380. PLIST_ENTRY pHead, plistEntry;
  381. PSUBDIR_SHARE_INFO pSubShareInfo;
  382. HANDLE hFind;
  383. DWORD status = ERROR_SUCCESS;
  384. DWORD dwLen;
  385. LPWSTR pszRootDir = NULL, pszPath = NULL;
  386. WIN32_FIND_DATA FindData;
  387. DWORD dwCount = 0;
  388. //
  389. // Chittur Subbaraman (chitturs) - 09/25/98
  390. //
  391. // This function first checks to see whether all the subshares
  392. // are indeed currently present. If it finds any subdir
  393. // corresponding to a subshare to be absent, then it removes
  394. // that subdir from the share list.
  395. //
  396. dwLen = lstrlenW( pResourceEntry->Params.Path );
  397. pszRootDir = ( LPWSTR ) LocalAlloc( LMEM_FIXED, ( dwLen + SMBSHARE_EXTRA_LEN ) * sizeof( WCHAR ) );
  398. if ( pszRootDir == NULL )
  399. {
  400. (g_LogEvent)(
  401. pResourceEntry->ResourceHandle,
  402. LOG_ERROR,
  403. L"Unable to allocate pszRootDir. Error: %1!u!.\n",
  404. status = GetLastError() );
  405. goto error_exit;
  406. }
  407. ( void ) StringCchCopy( pszRootDir, dwLen + SMBSHARE_EXTRA_LEN, pResourceEntry->Params.Path );
  408. //
  409. // If the path is not already terminated with \\ then add it.
  410. //
  411. if ( pszRootDir [dwLen-1] != L'\\' )
  412. pszRootDir [dwLen++] = L'\\';
  413. pszRootDir [dwLen] = L'\0' ;
  414. pszPath = LocalAlloc ( LMEM_FIXED, ( dwLen + SMBSHARE_EXTRA_LEN + NNLEN ) * sizeof ( WCHAR ) );
  415. if ( pszPath == NULL )
  416. {
  417. (g_LogEvent)(
  418. pResourceEntry->ResourceHandle,
  419. LOG_ERROR,
  420. L"Unable to allocate pszPath. Error: %1!u!.\n",
  421. status = GetLastError() );
  422. goto error_exit;
  423. }
  424. pHead = plistEntry = &pResourceEntry->SubDirList;
  425. for ( plistEntry = pHead->Flink;
  426. plistEntry != pHead;
  427. dwCount++)
  428. {
  429. if ( ClusWorkerCheckTerminate ( &pResourceEntry->NotifyWorker ) )
  430. {
  431. status = ERROR_SUCCESS;
  432. break;
  433. }
  434. pSubShareInfo = CONTAINING_RECORD( plistEntry, SUBDIR_SHARE_INFO, ListEntry );
  435. plistEntry = plistEntry->Flink;
  436. if ( lstrcmpW( pSubShareInfo->ShareName, pResourceEntry->Params.ShareName ))
  437. {
  438. //
  439. // This is not the root share
  440. //
  441. ( void ) StringCchCopy ( pszPath, dwLen + SMBSHARE_EXTRA_LEN + NNLEN, pszRootDir );
  442. ( void ) StringCchCat ( pszPath, dwLen + SMBSHARE_EXTRA_LEN + NNLEN, pSubShareInfo->ShareName );
  443. //
  444. // Get rid of the hidden share '$' sign for passing onto
  445. // FindFirstFile, if present. Only do this if the
  446. // "HideSubDirShares" option is chosen.
  447. //
  448. if ( pResourceEntry->Params.HideSubDirShares )
  449. {
  450. dwLen = lstrlenW( pszPath );
  451. if ( pszPath [dwLen-1] == L'$' )
  452. {
  453. pszPath [dwLen-1] = L'\0';
  454. }
  455. }
  456. hFind = FindFirstFile( pszPath, &FindData );
  457. if ( hFind == INVALID_HANDLE_VALUE )
  458. {
  459. status = GetLastError();
  460. (g_LogEvent)(
  461. pResourceEntry->ResourceHandle,
  462. LOG_ERROR,
  463. L"SmbpCheckForSubDirDeletion: Dir '%1' not found ...\n",
  464. pszPath
  465. );
  466. if ( status == ERROR_FILE_NOT_FOUND )
  467. {
  468. //
  469. // Delete the file share
  470. //
  471. status = NetShareDel( NULL, pSubShareInfo->ShareName, 0 );
  472. if ( (status != NERR_NetNameNotFound) &&
  473. (status != NO_ERROR) )
  474. {
  475. (g_LogEvent)(
  476. pResourceEntry->ResourceHandle,
  477. LOG_ERROR,
  478. L"SmbpCheckForSubDirDeletion: Error removing share '%1'. Error code = %2!u!...\n",
  479. pSubShareInfo->ShareName,
  480. status );
  481. } else
  482. {
  483. (g_LogEvent)(
  484. pResourceEntry->ResourceHandle,
  485. LOG_INFORMATION,
  486. L"SmbpCheckForSubDirDeletion: Removing share '%1'...\n",
  487. pSubShareInfo->ShareName );
  488. RemoveEntryList( &pSubShareInfo->ListEntry );
  489. LocalFree ( pSubShareInfo );
  490. }
  491. }
  492. else
  493. {
  494. (g_LogEvent)(
  495. pResourceEntry->ResourceHandle,
  496. LOG_ERROR,
  497. L"SmbpCheckForSubDirDeletion: Error in FindFirstFile for share '%1'. Error code = %2!u!....\n",
  498. pSubShareInfo->ShareName,
  499. status );
  500. }
  501. }
  502. else
  503. {
  504. if ( !FindClose ( hFind ) )
  505. {
  506. (g_LogEvent)(
  507. pResourceEntry->ResourceHandle,
  508. LOG_ERROR,
  509. L"CheckForSubDirDeletion: FindClose Failed. Error: %1!u!.\n",
  510. status = GetLastError () );
  511. }
  512. }
  513. }
  514. } // end of for loop
  515. error_exit:
  516. LocalFree ( pszRootDir );
  517. LocalFree ( pszPath );
  518. return(status);
  519. } // SmbpCheckForSubDirDeletion
  520. DWORD
  521. SmbpCheckAndBringSubSharesOnline (
  522. IN PSHARE_RESOURCE pResourceEntry,
  523. IN BOOL IsCheckAllSubDirs,
  524. IN PRESOURCE_STATUS pResourceStatus,
  525. IN PCLUS_WORKER pWorker,
  526. OUT LPWSTR *pszRootDirOut
  527. )
  528. /*++
  529. Routine Description:
  530. Check and bring online any newly added subdirectory shares.
  531. Arguments:
  532. pResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  533. IsCheckAllSubDirs - Check whether a subdir is a share or not
  534. pResourceStatus - A pointer to the RESOURCE_STATUS
  535. pWorker - A pointer to the worker thread
  536. pszRootDirOut - A pointer to the root share store
  537. Returns:
  538. ERROR_SUCCESS if successful.
  539. Win32 error code on failure.
  540. --*/
  541. {
  542. HANDLE hFind = INVALID_HANDLE_VALUE;
  543. WIN32_FIND_DATA FindData;
  544. WCHAR szPath [MAX_PATH+1];
  545. DWORD dwLen, dwShareLen;
  546. DWORD dwCount = 0;
  547. SHARE_INFO_502 shareInfo;
  548. PSHARE_INFO_502 pshareInfo = NULL;
  549. WCHAR szShareName [NNLEN+2];
  550. DWORD status = ERROR_SUCCESS;
  551. PSUBDIR_SHARE_INFO pSubShareInfo;
  552. PLIST_ENTRY plistEntry;
  553. RESOURCE_EXIT_STATE exitState;
  554. LPWSTR pszRootDir = NULL;
  555. //
  556. // Chittur Subbaraman (chitturs) - 09/25/98
  557. //
  558. // This function will be called either from SmbpShareOnlineThread
  559. // with the input parameter IsCheckAllSubDirs set to FALSE
  560. // or from SmbpShareNotifyThread with the parameter set to TRUE.
  561. // In the former case, this function will blindly make all the
  562. // subdirs under the root share as shares. In the latter case,
  563. // this function will first check whether a particular subdir
  564. // is a share and if not it will make it as a share.
  565. //
  566. dwLen = lstrlenW( pResourceEntry->Params.Path );
  567. plistEntry = &pResourceEntry->SubDirList;
  568. //
  569. // Allocate memory to store the root share here and
  570. // free it at the caller
  571. //
  572. pszRootDir = ( LPWSTR ) LocalAlloc( LMEM_FIXED, ( dwLen + SMBSHARE_EXTRA_LEN ) * sizeof( WCHAR ) );
  573. if ( pszRootDir == NULL )
  574. {
  575. (g_LogEvent)(
  576. pResourceEntry->ResourceHandle,
  577. LOG_ERROR,
  578. L"Unable to allocate pszRootDir. Error: %1!u!.\n",
  579. status = GetLastError() );
  580. goto error_exit;
  581. }
  582. ( void ) StringCchCopy( pszRootDir, dwLen + SMBSHARE_EXTRA_LEN, pResourceEntry->Params.Path );
  583. //
  584. // If the path is not already terminated with \\ then add it.
  585. //
  586. if ( pszRootDir [dwLen-1] != L'\\' )
  587. pszRootDir [dwLen++] = L'\\';
  588. //
  589. // Add '*' to search all the files.
  590. //
  591. pszRootDir [dwLen++] = L'*' ;
  592. pszRootDir [dwLen] = L'\0' ;
  593. ZeroMemory( &shareInfo, sizeof( shareInfo ) );
  594. shareInfo.shi502_path = szPath;
  595. shareInfo.shi502_netname = szShareName;
  596. shareInfo.shi502_type = STYPE_DISKTREE;
  597. shareInfo.shi502_remark = pResourceEntry->Params.Remark;
  598. shareInfo.shi502_max_uses = pResourceEntry->Params.MaxUsers;
  599. shareInfo.shi502_passwd = NULL;
  600. shareInfo.shi502_security_descriptor = pResourceEntry->Params.SecurityDescriptor;
  601. //
  602. // Find the first file in the root dir
  603. //
  604. if ( ( hFind = FindFirstFile( pszRootDir, &FindData ) ) == INVALID_HANDLE_VALUE ) {
  605. status = GetLastError () ;
  606. if ( status == ERROR_FILE_NOT_FOUND ) {
  607. status = ERROR_SUCCESS;
  608. } else {
  609. (g_LogEvent)(
  610. pResourceEntry->ResourceHandle,
  611. LOG_ERROR,
  612. L"CheckForSubDirAddition: FindFirstFile Failed For Root Share... Error: %1!u!.\n",
  613. status );
  614. }
  615. goto error_exit;
  616. }
  617. //
  618. // Remove the '*' so the same variable can be used later.
  619. //
  620. pszRootDir [dwLen-1] = L'\0' ;
  621. while ( status == ERROR_SUCCESS ) {
  622. if ( ClusWorkerCheckTerminate ( pWorker ) == TRUE ) {
  623. status = ERROR_SUCCESS;
  624. goto error_exit;
  625. }
  626. if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
  627. //
  628. // Check only subdirectories, not files
  629. //
  630. dwShareLen = lstrlenW( FindData.cFileName );
  631. if ( dwShareLen <= NNLEN && (dwLen + dwShareLen < MAX_PATH) ) // A safety check for overflow
  632. {
  633. ( void ) StringCchCopy( szShareName, RTL_NUMBER_OF ( szShareName ), FindData.cFileName );
  634. if ( szShareName[0] == L'.' )
  635. {
  636. if ( szShareName [1] == L'\0' ||
  637. szShareName[1] == L'.' && szShareName [2] == L'\0' ) {
  638. goto skip;
  639. }
  640. }
  641. if ( pResourceEntry->Params.HideSubDirShares )
  642. ( void ) StringCchCat( szShareName, RTL_NUMBER_OF ( szShareName ), L"$" );
  643. ( void ) StringCchCopy ( szPath, RTL_NUMBER_OF ( szPath ), pszRootDir );
  644. ( void ) StringCchCat ( szPath, RTL_NUMBER_OF ( szPath ), FindData.cFileName );
  645. if ( IsCheckAllSubDirs == TRUE )
  646. {
  647. //
  648. // If this call is made from the notify thread,
  649. // try to see whether a particular subdir is a
  650. // share
  651. //
  652. status = NetShareGetInfo( NULL,
  653. szShareName,
  654. 502, // return a SHARE_INFO_502 structure
  655. (LPBYTE *) &pshareInfo );
  656. } else
  657. {
  658. //
  659. // If this call is made from the online thread,
  660. // assume that the subdir is not a share (since
  661. // it would have been removed as a share the
  662. // most recent time when it was made offline).
  663. //
  664. status = NERR_NetNameNotFound;
  665. }
  666. if ( status == NERR_NetNameNotFound )
  667. {
  668. status = NetShareAdd( NULL, 502, (PBYTE)&shareInfo, NULL );
  669. if ( status == ERROR_SUCCESS )
  670. {
  671. pSubShareInfo = (PSUBDIR_SHARE_INFO) LocalAlloc( LMEM_FIXED, sizeof(SUBDIR_SHARE_INFO) );
  672. if ( pSubShareInfo == NULL )
  673. {
  674. (g_LogEvent)(
  675. pResourceEntry->ResourceHandle,
  676. LOG_ERROR,
  677. L"SmbpCheckAndBringSubSharesOnline: Unable to allocate pSubShareInfo. Error: %1!u!.\n",
  678. status = GetLastError() );
  679. goto error_exit;
  680. }
  681. ( void ) StringCchCopy ( pSubShareInfo->ShareName, RTL_NUMBER_OF ( pSubShareInfo->ShareName ), szShareName );
  682. InsertTailList( plistEntry, &pSubShareInfo->ListEntry );
  683. //
  684. // Set the caching flags for this entry.
  685. //
  686. status = SmbpSetCacheFlags( pResourceEntry,
  687. szShareName );
  688. if ( status != ERROR_SUCCESS ) {
  689. goto error_exit;
  690. }
  691. (g_LogEvent)(
  692. pResourceEntry->ResourceHandle,
  693. LOG_INFORMATION,
  694. L"SmbpCheckAndBringSubSharesOnline: Adding share '%1'...\n",
  695. pSubShareInfo->ShareName);
  696. if ( IsCheckAllSubDirs == FALSE )
  697. {
  698. if ( (dwCount++ % 100) == 0)
  699. {
  700. pResourceStatus->CheckPoint++;
  701. exitState = (g_SetResourceStatus)( pResourceEntry->ResourceHandle,
  702. pResourceStatus );
  703. if ( exitState == ResourceExitStateTerminate )
  704. {
  705. status = ERROR_OPERATION_ABORTED;
  706. goto error_exit;
  707. }
  708. }
  709. }
  710. }
  711. else
  712. {
  713. //
  714. // ignore this error but log that something went wrong
  715. //
  716. (g_LogEvent)(
  717. pResourceEntry->ResourceHandle,
  718. LOG_ERROR,
  719. L"SmbpCheckAndBringSubSharesOnline: NetShareAdd failed for %1!ws! Error: %2!u!.\n",
  720. szShareName,
  721. status );
  722. status = ERROR_SUCCESS;
  723. }
  724. } else
  725. {
  726. if ( pshareInfo != NULL )
  727. {
  728. NetApiBufferFree( pshareInfo );
  729. }
  730. }
  731. }
  732. else
  733. {
  734. (g_LogEvent)(
  735. pResourceEntry->ResourceHandle,
  736. LOG_ERROR,
  737. L"SmbpCheckAndBringSubSharesOnline: NetShareAdd Share not added for subdir due to illegal share name length '%1!ws!'.\n",
  738. FindData.cFileName );
  739. }
  740. }
  741. skip:
  742. if ( !FindNextFile( hFind, &FindData ) )
  743. {
  744. status = GetLastError ();
  745. }
  746. } // end of while loop
  747. if ( status == ERROR_NO_MORE_FILES )
  748. {
  749. status = ERROR_SUCCESS;
  750. }
  751. else
  752. {
  753. (g_LogEvent)(
  754. pResourceEntry->ResourceHandle,
  755. LOG_ERROR,
  756. L"CheckForSubDirAddition: FindNextFile Failed. Error: %1!u!.\n",
  757. status );
  758. }
  759. error_exit:
  760. if ( hFind != INVALID_HANDLE_VALUE )
  761. {
  762. if( !FindClose (hFind) )
  763. {
  764. (g_LogEvent)(
  765. pResourceEntry->ResourceHandle,
  766. LOG_ERROR,
  767. L"SmbpCheckAndBringSubSharesOnline: FindClose Failed. Error: %1!u!.\n",
  768. status = GetLastError () );
  769. }
  770. }
  771. *pszRootDirOut = pszRootDir;
  772. return(status);
  773. } // SmbpCheckAndBringSubSharesOnline
  774. DWORD
  775. SmbShareOnlineThread(
  776. IN PCLUS_WORKER pWorker,
  777. IN PSHARE_RESOURCE ResourceEntry
  778. )
  779. /*++
  780. Routine Description:
  781. Brings a share resource online.
  782. Arguments:
  783. pWorker - Supplies the worker structure
  784. ResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  785. Returns:
  786. ERROR_SUCCESS if successful.
  787. Win32 error code on failure.
  788. --*/
  789. {
  790. SHARE_INFO_502 shareInfo;
  791. DWORD retry = MAX_RETRIES;
  792. DWORD status;
  793. RESOURCE_STATUS resourceStatus;
  794. LPWSTR nameOfPropInError;
  795. BOOL bIsExistingDfsRoot = FALSE;
  796. BOOL bDfsRootCreationFailed = FALSE;
  797. DWORD dwLen;
  798. ResUtilInitializeResourceStatus( &resourceStatus );
  799. resourceStatus.ResourceState = ClusterResourceOnlinePending;
  800. // resourceStatus.CheckPoint = 1;
  801. //
  802. // Read parameters.
  803. //
  804. status = ResUtilGetPropertiesToParameterBlock( ResourceEntry->ParametersKey,
  805. SmbShareResourcePrivateProperties,
  806. (LPBYTE) &ResourceEntry->Params,
  807. TRUE, // CheckForRequiredProperties
  808. &nameOfPropInError );
  809. if (status != ERROR_SUCCESS) {
  810. (g_LogEvent)(
  811. ResourceEntry->ResourceHandle,
  812. LOG_ERROR,
  813. L"Unable to read the '%1' property. Error: %2!u!.\n",
  814. (nameOfPropInError == NULL ? L"" : nameOfPropInError),
  815. status );
  816. goto exit;
  817. }
  818. if ( (ResourceEntry->Params.SecurityDescriptorSize != 0) &&
  819. !IsValidSecurityDescriptor(ResourceEntry->Params.SecurityDescriptor) ) {
  820. status = GetLastError();
  821. goto exit;
  822. }
  823. while ( retry-- )
  824. {
  825. //
  826. // Make sure the path does _NOT_ have a trailing backslash or it will fail to
  827. // come online. But accept paths of the form E:\.
  828. //
  829. dwLen = ( DWORD ) wcslen( ResourceEntry->Params.Path );
  830. if ( ( ResourceEntry->Params.Path[ dwLen - 1 ] == L'\\' ) &&
  831. ( dwLen > 3 ) )
  832. {
  833. ResourceEntry->Params.Path[ dwLen - 1 ] = L'\0'; // wack it.
  834. }
  835. ZeroMemory( &shareInfo, sizeof( shareInfo ) );
  836. shareInfo.shi502_netname = ResourceEntry->Params.ShareName;
  837. shareInfo.shi502_type = STYPE_DISKTREE;
  838. shareInfo.shi502_remark = ResourceEntry->Params.Remark;
  839. shareInfo.shi502_max_uses = ResourceEntry->Params.MaxUsers;
  840. shareInfo.shi502_path = ResourceEntry->Params.Path;
  841. shareInfo.shi502_passwd = NULL;
  842. shareInfo.shi502_security_descriptor = ResourceEntry->Params.SecurityDescriptor;
  843. status = NetShareAdd( NULL, 502, (PBYTE)&shareInfo, NULL );
  844. if ( status == ERROR_SUCCESS ) {
  845. status = SmbpSetCacheFlags( ResourceEntry,
  846. ResourceEntry->Params.ShareName );
  847. if ( status != ERROR_SUCCESS ) {
  848. goto exit;
  849. }
  850. break;
  851. }
  852. // If we get a failure about the server not being started, then
  853. // try to start the server and wait a little while.
  854. if ( status != ERROR_SUCCESS ) {
  855. WCHAR errorValue[20];
  856. ( void ) StringCchPrintf( errorValue, RTL_NUMBER_OF ( errorValue ), L"%u", status );
  857. ClusResLogSystemEventByKey1(ResourceEntry->ResourceKey,
  858. LOG_CRITICAL,
  859. RES_SMB_SHARE_CANT_ADD,
  860. errorValue);
  861. if ( status == NERR_ServerNotStarted ) {
  862. ResUtilStartResourceService( SMB_SVCNAME,
  863. NULL );
  864. Sleep( 500 );
  865. } else if ( status == NERR_DuplicateShare ) {
  866. (g_LogEvent)(
  867. ResourceEntry->ResourceHandle,
  868. LOG_WARNING,
  869. L"Share %1!ws! is online already; deleting share and creating it again\n",
  870. ResourceEntry->Params.ShareName);
  871. //
  872. // Delete the share and try again.
  873. //
  874. status = NetShareDel( NULL, ResourceEntry->Params.ShareName, 0 );
  875. if ( status == NERR_IsDfsShare )
  876. {
  877. //
  878. // Chittur Subbaraman (chitturs) - 2/12/99
  879. //
  880. // Reset the state info in the dfs driver dfs.sys
  881. // and stop it. This will let srv.sys let you delete
  882. // the share.
  883. //
  884. status = SmbpResetDfs( ResourceEntry );
  885. //
  886. // If we can't do this exit, else retry deleting and
  887. // adding the share once again
  888. //
  889. if (status != ERROR_SUCCESS) {
  890. (g_LogEvent)(
  891. ResourceEntry->ResourceHandle,
  892. LOG_ERROR,
  893. L"SmbpResetDfs for Share %1!ws! failed with error %2!u!\n",
  894. ResourceEntry->Params.ShareName,
  895. status);
  896. goto exit;
  897. }
  898. (g_LogEvent)(
  899. ResourceEntry->ResourceHandle,
  900. LOG_ERROR,
  901. L"Informing DFS that share %1!ws! is not a dfs root \n",
  902. ResourceEntry->Params.ShareName);
  903. } else
  904. {
  905. (g_LogEvent)(
  906. ResourceEntry->ResourceHandle,
  907. LOG_INFORMATION,
  908. L"Share %1!ws! deleted successfully ! \n",
  909. ResourceEntry->Params.ShareName);
  910. }
  911. } else {
  912. (g_LogEvent)(
  913. ResourceEntry->ResourceHandle,
  914. LOG_ERROR,
  915. L"Error creating share. Error: %1!u!.\n",
  916. status );
  917. goto exit;
  918. }
  919. }
  920. } // End for while ( retry-- )
  921. if ( status == ERROR_SUCCESS )
  922. {
  923. // The share is now online, bring the subshares online
  924. PLIST_ENTRY plistEntry;
  925. PSUBDIR_SHARE_INFO pSubShareInfo;
  926. LPWSTR pszRootDir;
  927. plistEntry = &ResourceEntry->SubDirList;
  928. //
  929. // Store the Root share. This info is used to delete the share.
  930. //
  931. pSubShareInfo = (PSUBDIR_SHARE_INFO) LocalAlloc( LMEM_FIXED, sizeof (SUBDIR_SHARE_INFO) );
  932. if ( pSubShareInfo == NULL ) {
  933. (g_LogEvent)(
  934. ResourceEntry->ResourceHandle,
  935. LOG_ERROR,
  936. L"Unable to allocate pSubShareInfo. Error: %1!u!.\n",
  937. status = GetLastError() );
  938. goto exit;
  939. }
  940. ( void ) StringCchCopy ( pSubShareInfo->ShareName, RTL_NUMBER_OF ( pSubShareInfo->ShareName ), ResourceEntry->Params.ShareName );
  941. InsertTailList( plistEntry, &pSubShareInfo->ListEntry );
  942. if ( ResourceEntry->Params.ShareSubDirs ) {
  943. // Chittur Subbaraman (chitturs) - 09/25/98
  944. //
  945. // Try to bring the subshares online.
  946. // If there is a failure in bringing subshares online,
  947. // pretend all is well since at least the root
  948. // share has been successfully created. However, we
  949. // write an entry into the log.
  950. //
  951. SmbpCheckAndBringSubSharesOnline ( ResourceEntry,
  952. FALSE,
  953. &resourceStatus,
  954. &ResourceEntry->PendingThread,
  955. &pszRootDir
  956. );
  957. if ( ClusWorkerCheckTerminate( &ResourceEntry->PendingThread ) ) {
  958. (g_LogEvent)(
  959. ResourceEntry->ResourceHandle,
  960. LOG_INFORMATION,
  961. L"SmbpShareOnlineThread: Terminating... !!!\n"
  962. );
  963. status = ERROR_SUCCESS;
  964. LocalFree ( pszRootDir );
  965. goto exit;
  966. }
  967. // Chittur Subbaraman (chitturs) - 09/25/98
  968. //
  969. // Create a change notification handle for any subdirectory
  970. // additions/deletions and a notify thread which continuously
  971. // checks and acts upon any such notifications. Do this
  972. // only once at the beginning. The notification thread
  973. // closes the handle at termination time.
  974. //
  975. ResourceEntry->NotifyHandle = FindFirstChangeNotification(
  976. pszRootDir,
  977. FALSE,
  978. FILE_NOTIFY_CHANGE_DIR_NAME
  979. );
  980. LocalFree ( pszRootDir );
  981. if ( ResourceEntry->NotifyHandle == INVALID_HANDLE_VALUE )
  982. {
  983. (g_LogEvent)(
  984. ResourceEntry->ResourceHandle,
  985. LOG_ERROR,
  986. L"SmbpShareOnlineThread: FindFirstChange Notification Failed. Error: %1!u!.\n",
  987. GetLastError ());
  988. status = ERROR_SUCCESS;
  989. goto exit;
  990. }
  991. goto exit;
  992. }
  993. } // End for root share successfully created.
  994. //
  995. // Chittur Subbaraman (chitturs) - 2/10/99
  996. //
  997. // If the user requests for this resource to be a DFS root, the
  998. // dfs root will be created/accepted and the dfs registry
  999. // checkpoints will be added. On the other hand, if the user
  1000. // wants this resource not to function as a dfs root any more,
  1001. // that case is also taken care of.
  1002. //
  1003. status = SmbpHandleDfsRoot( ResourceEntry, &bIsExistingDfsRoot );
  1004. if ( status != ERROR_SUCCESS ) {
  1005. (g_LogEvent)(
  1006. ResourceEntry->ResourceHandle,
  1007. LOG_ERROR,
  1008. L"SmbpHandleDfsRoot for Share %1!ws! failed with error %2!u!\n",
  1009. ResourceEntry->Params.ShareName,
  1010. status);
  1011. bDfsRootCreationFailed = TRUE;
  1012. goto exit;
  1013. }
  1014. if ( bIsExistingDfsRoot ) {
  1015. (g_LogEvent)(
  1016. ResourceEntry->ResourceHandle,
  1017. LOG_INFORMATION,
  1018. L"Share %1!ws! is a dfs root, online dfs\n",
  1019. ResourceEntry->Params.ShareName);
  1020. status = SmbpPrepareOnlineDfsRoot( ResourceEntry );
  1021. if ( status != ERROR_SUCCESS ) {
  1022. bDfsRootCreationFailed = TRUE;
  1023. }
  1024. }
  1025. exit:
  1026. if ( status != ERROR_SUCCESS ) {
  1027. if ( bDfsRootCreationFailed ) {
  1028. WCHAR szErrorString[12];
  1029. ( void ) StringCchPrintf ( szErrorString, RTL_NUMBER_OF ( szErrorString ), L"%u", status);
  1030. ClusResLogSystemEventByKeyData1( ResourceEntry->ResourceKey,
  1031. LOG_CRITICAL,
  1032. RES_SMB_CANT_ONLINE_DFS_ROOT,
  1033. sizeof( status ),
  1034. &status,
  1035. szErrorString );
  1036. } else {
  1037. ClusResLogSystemEventByKeyData( ResourceEntry->ResourceKey,
  1038. LOG_CRITICAL,
  1039. RES_SMB_CANT_CREATE_SHARE,
  1040. sizeof( status ),
  1041. &status );
  1042. }
  1043. (g_LogEvent)(
  1044. ResourceEntry->ResourceHandle,
  1045. LOG_ERROR,
  1046. L"Error %1!u! bringing share %2!ws!, path %3!ws! online.\n",
  1047. status,
  1048. ResourceEntry->Params.ShareName,
  1049. ResourceEntry->Params.Path );
  1050. resourceStatus.ResourceState = ClusterResourceFailed;
  1051. } else {
  1052. resourceStatus.ResourceState = ClusterResourceOnline;
  1053. }
  1054. ResourceEntry->State = resourceStatus.ResourceState;
  1055. (g_SetResourceStatus)( ResourceEntry->ResourceHandle,
  1056. &resourceStatus );
  1057. return(status);
  1058. } // SmbShareOnlineThread
  1059. RESID
  1060. WINAPI
  1061. SmbShareOpen(
  1062. IN LPCWSTR ResourceName,
  1063. IN HKEY ResourceKey,
  1064. IN RESOURCE_HANDLE ResourceHandle
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. Open routine for SMB share resource.
  1069. Arguments:
  1070. ResourceName - supplies the resource name
  1071. ResourceKey - Supplies handle to resource's cluster registry key.
  1072. ResourceHandle - the resource handle to be supplied with SetResourceStatus
  1073. is called.
  1074. Return Value:
  1075. RESID of created resource
  1076. Zero on failure
  1077. --*/
  1078. {
  1079. DWORD status;
  1080. RESID resid = 0;
  1081. HKEY parametersKey = NULL;
  1082. HKEY resKey = NULL;
  1083. PSHARE_RESOURCE resourceEntry = NULL;
  1084. DWORD computerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
  1085. HCLUSTER hCluster;
  1086. //
  1087. // Get a handle to our resource key so that we can get our name later
  1088. // if we need to log an event.
  1089. //
  1090. status = ClusterRegOpenKey( ResourceKey,
  1091. L"",
  1092. KEY_READ,
  1093. &resKey);
  1094. if (status != ERROR_SUCCESS) {
  1095. (g_LogEvent)(ResourceHandle,
  1096. LOG_ERROR,
  1097. L"Unable to open resource key. Error: %1!u!.\n",
  1098. status );
  1099. SetLastError( status );
  1100. return(0);
  1101. }
  1102. //
  1103. // Open the Parameters key for this resource.
  1104. //
  1105. status = ClusterRegOpenKey( ResourceKey,
  1106. PARAM_KEYNAME__PARAMETERS,
  1107. KEY_ALL_ACCESS,
  1108. &parametersKey );
  1109. if ( status != ERROR_SUCCESS ) {
  1110. (g_LogEvent)(
  1111. ResourceHandle,
  1112. LOG_ERROR,
  1113. L"Unable to open Parameters key. Error: %1!u!.\n",
  1114. status );
  1115. goto exit;
  1116. }
  1117. //
  1118. // Allocate a resource entry.
  1119. //
  1120. resourceEntry = (PSHARE_RESOURCE) LocalAlloc( LMEM_FIXED, sizeof(SHARE_RESOURCE) );
  1121. if ( resourceEntry == NULL ) {
  1122. status = GetLastError();
  1123. (g_LogEvent)(
  1124. ResourceHandle,
  1125. LOG_ERROR,
  1126. L"Unable to allocate resource entry structure. Error: %1!u!.\n",
  1127. status );
  1128. goto exit;
  1129. }
  1130. //
  1131. // Initialize the resource entry..
  1132. //
  1133. ZeroMemory( resourceEntry, sizeof(SHARE_RESOURCE) );
  1134. resourceEntry->ResId = (RESID)resourceEntry; // for validation
  1135. resourceEntry->ResourceHandle = ResourceHandle;
  1136. resourceEntry->ResourceKey = resKey;
  1137. resourceEntry->ParametersKey = parametersKey;
  1138. resourceEntry->State = ClusterResourceOffline;
  1139. resourceEntry->NotifyHandle = INVALID_HANDLE_VALUE;
  1140. InitializeListHead( &resourceEntry->SubDirList );
  1141. hCluster = OpenCluster( NULL );
  1142. if ( !hCluster ) {
  1143. status = GetLastError();
  1144. (g_LogEvent)(
  1145. ResourceHandle,
  1146. LOG_ERROR,
  1147. L"Unable to open cluster. Error: %1!u!.\n",
  1148. status );
  1149. goto exit;
  1150. }
  1151. resourceEntry->hResource = OpenClusterResource( hCluster,
  1152. ResourceName );
  1153. CloseCluster( hCluster );
  1154. if ( !resourceEntry->hResource ) {
  1155. status = GetLastError();
  1156. (g_LogEvent)(
  1157. ResourceHandle,
  1158. LOG_ERROR,
  1159. L"Unable to open cluster resource. Error: %1!u!.\n",
  1160. status );
  1161. goto exit;
  1162. }
  1163. if ( !GetComputerNameW( &resourceEntry->ComputerName[0],
  1164. &computerNameSize ) ) {
  1165. status = GetLastError();
  1166. (g_LogEvent)(
  1167. ResourceHandle,
  1168. LOG_ERROR,
  1169. L"Unable to get computer name. Error: %1!u!.\n",
  1170. status );
  1171. goto exit;
  1172. }
  1173. resid = (RESID)resourceEntry;
  1174. exit:
  1175. if ( resid == 0 ) {
  1176. if ( parametersKey != NULL ) {
  1177. ClusterRegCloseKey( parametersKey );
  1178. }
  1179. if ( resKey != NULL ) {
  1180. ClusterRegCloseKey( resKey );
  1181. }
  1182. if ( resourceEntry &&
  1183. resourceEntry->hResource ) {
  1184. CloseClusterResource( resourceEntry->hResource );
  1185. }
  1186. LocalFree( resourceEntry );
  1187. }
  1188. SetLastError( status );
  1189. return(resid);
  1190. } // SmbShareOpen
  1191. DWORD
  1192. WINAPI
  1193. SmbShareOnline(
  1194. IN RESID ResourceId,
  1195. IN OUT PHANDLE EventHandle
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. Online routine for File Share resource.
  1200. Arguments:
  1201. Resource - supplies resource id to be brought online
  1202. EventHandle - supplies a pointer to a handle to signal on error.
  1203. Return Value:
  1204. ERROR_SUCCESS if successful.
  1205. ERROR_RESOURCE_NOT_FOUND if RESID is not valid.
  1206. ERROR_RESOURCE_NOT_AVAILABLE if resource was arbitrated but failed to
  1207. acquire 'ownership'.
  1208. Win32 error code if other failure.
  1209. --*/
  1210. {
  1211. DWORD status;
  1212. PSHARE_RESOURCE resourceEntry;
  1213. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  1214. if ( resourceEntry == NULL ) {
  1215. DBG_PRINT( "SmbShare: Online request for a nonexistent resource id 0x%p\n",
  1216. ResourceId );
  1217. return(ERROR_RESOURCE_NOT_FOUND);
  1218. }
  1219. if ( resourceEntry->ResId != ResourceId ) {
  1220. (g_LogEvent)(
  1221. resourceEntry->ResourceHandle,
  1222. LOG_ERROR,
  1223. L"Online resource sanity check failed! ResourceId = %1!u!.\n",
  1224. ResourceId );
  1225. return(ERROR_RESOURCE_NOT_FOUND);
  1226. }
  1227. #ifdef LOG_VERBOSE
  1228. (g_LogEvent)(
  1229. resourceEntry->ResourceHandle,
  1230. LOG_INFORMATION,
  1231. L"Online request.\n" );
  1232. #endif
  1233. resourceEntry->State = ClusterResourceOffline;
  1234. status = ClusWorkerCreate( &resourceEntry->PendingThread,
  1235. SmbShareOnlineThread,
  1236. resourceEntry );
  1237. if ( status != ERROR_SUCCESS ) {
  1238. resourceEntry->State = ClusterResourceFailed;
  1239. (g_LogEvent)(
  1240. resourceEntry->ResourceHandle,
  1241. LOG_ERROR,
  1242. L"Online: Unable to start thread, status %1!u!.\n",
  1243. status
  1244. );
  1245. } else {
  1246. status = ERROR_IO_PENDING;
  1247. }
  1248. return(status);
  1249. } // SmbShareOnline
  1250. DWORD
  1251. SmbShareDoTerminate (
  1252. IN PSHARE_RESOURCE ResourceEntry,
  1253. IN PRESOURCE_STATUS presourceStatus
  1254. )
  1255. /*++
  1256. Routine Description:
  1257. Do the actual Terminate work for File Share resources.
  1258. Arguments:
  1259. ResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  1260. presourceStatus - A pointer to the RESOURCE_STATUS. This will be NULL if called from TERMINATE.
  1261. Returns:
  1262. ERROR_SUCCESS if successful.
  1263. Win32 error code on failure. If more than one share delete fails then
  1264. the last error is returned.
  1265. --*/
  1266. {
  1267. DWORD status = ERROR_SUCCESS, dwRet;
  1268. PLIST_ENTRY pHead, plistEntry;
  1269. PSUBDIR_SHARE_INFO pSubShareInfo;
  1270. #define SMB_DELETED_SHARES_REPORT_FREQ 100
  1271. DWORD dwSharesDeleted = SMB_DELETED_SHARES_REPORT_FREQ;
  1272. DWORD dwRetryCount;
  1273. BOOL bRetry;
  1274. RESOURCE_EXIT_STATE exit;
  1275. //
  1276. // Chittur Subbaraman (chitturs) - 09/25/98
  1277. //
  1278. // Terminate the notification thread first, so you can
  1279. // clean up even if the notification thread is forced to
  1280. // stop in the middle of its task. Also close the notification
  1281. // handle.
  1282. //
  1283. ClusWorkerTerminate( &ResourceEntry->NotifyWorker );
  1284. if ( ResourceEntry->NotifyHandle )
  1285. {
  1286. FindCloseChangeNotification ( ResourceEntry->NotifyHandle );
  1287. ResourceEntry->NotifyHandle = INVALID_HANDLE_VALUE;
  1288. }
  1289. (g_LogEvent)(
  1290. ResourceEntry->ResourceHandle,
  1291. LOG_INFORMATION,
  1292. L"SmbShareDoTerminate: SmbpShareNotifyWorker Terminated... !!!\n"
  1293. );
  1294. pHead = plistEntry = &ResourceEntry->SubDirList;
  1295. for ( plistEntry = pHead->Flink;
  1296. plistEntry != pHead;
  1297. dwSharesDeleted--
  1298. )
  1299. {
  1300. pSubShareInfo = CONTAINING_RECORD( plistEntry, SUBDIR_SHARE_INFO, ListEntry );
  1301. dwRetryCount = 1;
  1302. bRetry = FALSE;
  1303. do
  1304. {
  1305. dwRet = NetShareDel( NULL, pSubShareInfo->ShareName, 0 );
  1306. status = dwRet;
  1307. if ( dwRet != NO_ERROR )
  1308. {
  1309. (g_LogEvent)(
  1310. ResourceEntry->ResourceHandle,
  1311. LOG_ERROR,
  1312. L"Error removing share '%1'. Error %2!u!.\n",
  1313. pSubShareInfo->ShareName,
  1314. dwRet );
  1315. if (dwRet == NERR_IsDfsShare && !bRetry)
  1316. {
  1317. //
  1318. // Chittur Subbaraman (chitturs) - 2/12/99
  1319. //
  1320. // If this is a dfs root, reset the dfs driver and
  1321. // stop it. This will let you delete the share.
  1322. //
  1323. dwRet = SmbpResetDfs( ResourceEntry );
  1324. //
  1325. // If this fails, log an error
  1326. // else try and offline the resource again.
  1327. //
  1328. if (dwRet == ERROR_SUCCESS)
  1329. {
  1330. bRetry = TRUE;
  1331. }
  1332. else
  1333. {
  1334. (g_LogEvent)(
  1335. ResourceEntry->ResourceHandle,
  1336. LOG_ERROR,
  1337. L"Error in offlining the dfs root at this share '%1'. Error %2!u!.\n",
  1338. pSubShareInfo->ShareName,
  1339. dwRet );
  1340. status = dwRet;
  1341. }
  1342. }
  1343. }
  1344. } while (dwRetryCount-- && bRetry);
  1345. //
  1346. // if we're updating our status to resmon, do so every
  1347. // SMB_DELETED_SHARES_REPORT_FREQ shares
  1348. //
  1349. if ( presourceStatus && ( dwSharesDeleted == 0 )) {
  1350. presourceStatus->CheckPoint++;
  1351. exit = (g_SetResourceStatus)( ResourceEntry->ResourceHandle,
  1352. presourceStatus );
  1353. if ( exit == ResourceExitStateTerminate ) {
  1354. status = ERROR_OPERATION_ABORTED;
  1355. }
  1356. dwSharesDeleted = SMB_DELETED_SHARES_REPORT_FREQ;
  1357. }
  1358. plistEntry = plistEntry->Flink;
  1359. LocalFree (pSubShareInfo);
  1360. }
  1361. // This should initialize the list back to NULL
  1362. InitializeListHead(pHead);
  1363. ResourceEntry->bDfsRootNeedsMonitoring = FALSE;
  1364. return(status);
  1365. } // SmbShareDoTerminate
  1366. DWORD
  1367. SmbShareOfflineThread (
  1368. IN PCLUS_WORKER pWorker,
  1369. IN PSHARE_RESOURCE ResourceEntry
  1370. )
  1371. /*++
  1372. Routine Description:
  1373. Brings a share resource offline.
  1374. Do the actual Terminate work for File Share resources.
  1375. Arguments:
  1376. pWorker - Supplies the worker structure
  1377. ResourceEntry - A pointer to the SHARE_RESOURCE block for this resource.
  1378. Returns:
  1379. ERROR_SUCCESS if successful.
  1380. Win32 error code on failure.
  1381. --*/
  1382. {
  1383. RESOURCE_STATUS resourceStatus;
  1384. DWORD status;
  1385. ResUtilInitializeResourceStatus( &resourceStatus );
  1386. resourceStatus.ResourceState = ClusterResourceOfflinePending;
  1387. resourceStatus.ResourceState = (status = SmbShareDoTerminate (ResourceEntry, &resourceStatus)) == ERROR_SUCCESS?
  1388. ClusterResourceOffline:
  1389. ClusterResourceFailed;
  1390. (g_SetResourceStatus)( ResourceEntry->ResourceHandle,
  1391. &resourceStatus );
  1392. ResourceEntry->State = resourceStatus.ResourceState;
  1393. (g_LogEvent)(
  1394. ResourceEntry->ResourceHandle,
  1395. LOG_INFORMATION,
  1396. L"Smbshare is now offline.\n" );
  1397. return(status);
  1398. } // SmbShareOfflineThread
  1399. VOID
  1400. WINAPI
  1401. SmbShareTerminate(
  1402. IN RESID ResourceId
  1403. )
  1404. /*++
  1405. Routine Description:
  1406. Terminate routine for File Share resource.
  1407. Arguments:
  1408. ResourceId - Supplies resource id to be terminated
  1409. Return Value:
  1410. None.
  1411. --*/
  1412. {
  1413. PSHARE_RESOURCE resourceEntry;
  1414. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  1415. if ( resourceEntry == NULL ) {
  1416. DBG_PRINT( "SmbShare: Terminate request for a nonexistent resource id 0x%p\n",
  1417. ResourceId );
  1418. return;
  1419. }
  1420. if ( resourceEntry->ResId != ResourceId ) {
  1421. (g_LogEvent)(
  1422. resourceEntry->ResourceHandle,
  1423. LOG_ERROR,
  1424. L"Terminate resource sanity check failed! ResourceId = %1!u!.\n",
  1425. ResourceId );
  1426. return;
  1427. }
  1428. #ifdef LOG_VERBOSE
  1429. (g_LogEvent)(
  1430. resourceEntry->ResourceHandle,
  1431. LOG_INFORMATION,
  1432. L"Terminate request.\n" );
  1433. #endif
  1434. ClusWorkerTerminate( &resourceEntry->PendingThread );
  1435. //
  1436. // Terminate the resource.
  1437. //
  1438. SmbShareDoTerminate( resourceEntry, NULL);
  1439. } // SmbShareTerminate
  1440. DWORD
  1441. WINAPI
  1442. SmbShareOffline(
  1443. IN RESID ResourceId
  1444. )
  1445. /*++
  1446. Routine Description:
  1447. Offline routine for File Share resource.
  1448. Arguments:
  1449. ResourceId - Supplies the resource it to be taken offline
  1450. Return Value:
  1451. ERROR_SUCCESS - The request completed successfully and the resource is
  1452. offline.
  1453. ERROR_RESOURCE_NOT_FOUND - RESID is not valid.
  1454. --*/
  1455. {
  1456. DWORD status;
  1457. PSHARE_RESOURCE resourceEntry;
  1458. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  1459. if ( resourceEntry == NULL ) {
  1460. DBG_PRINT( "SmbShare: Offline request for a nonexistent resource id 0x%p\n",
  1461. ResourceId );
  1462. return(ERROR_RESOURCE_NOT_FOUND);
  1463. }
  1464. if ( resourceEntry->ResId != ResourceId ) {
  1465. (g_LogEvent)(
  1466. resourceEntry->ResourceHandle,
  1467. LOG_ERROR,
  1468. L"Offline resource sanity check failed! ResourceId = %1!u!.\n",
  1469. ResourceId );
  1470. return(ERROR_RESOURCE_NOT_FOUND);
  1471. }
  1472. #ifdef LOG_VERBOSE
  1473. (g_LogEvent)(
  1474. resourceEntry->ResourceHandle,
  1475. LOG_INFORMATION,
  1476. L"Offline request.\n" );
  1477. #endif
  1478. //
  1479. // Terminate the resource.
  1480. //
  1481. // ClusWorkerTerminate( &resourceEntry->OfflineThread );
  1482. status = ClusWorkerCreate( &resourceEntry->PendingThread,
  1483. SmbShareOfflineThread,
  1484. resourceEntry );
  1485. if ( status != ERROR_SUCCESS ) {
  1486. resourceEntry->State = ClusterResourceFailed;
  1487. (g_LogEvent)(
  1488. resourceEntry->ResourceHandle,
  1489. LOG_ERROR,
  1490. L"Offline: Unable to start thread, status %1!u!.\n",
  1491. status
  1492. );
  1493. } else {
  1494. status = ERROR_IO_PENDING;
  1495. }
  1496. return status;
  1497. } // SmbShareOffline
  1498. BOOL
  1499. SmbShareCheckIsAlive(
  1500. IN PSHARE_RESOURCE ResourceEntry,
  1501. IN BOOL IsAliveCheck
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. Check to see if the resource is alive for File Share resources.
  1506. Arguments:
  1507. ResourceEntry - Supplies the resource entry for the resource to polled.
  1508. Return Value:
  1509. TRUE - Resource is alive and well
  1510. FALSE - Resource is toast.
  1511. --*/
  1512. {
  1513. DWORD status;
  1514. BOOL success = TRUE;
  1515. PSHARE_INFO_502 shareInfo;
  1516. WCHAR szErrorString[12];
  1517. EnterCriticalSection( &SmbShareLock );
  1518. //
  1519. // Determine if the resource is online.
  1520. //
  1521. status = NetShareGetInfo( NULL,
  1522. ResourceEntry->Params.ShareName,
  1523. 502, // return a SHARE_INFO_502 structure
  1524. (LPBYTE *) &shareInfo );
  1525. if ( status == NERR_NetNameNotFound ) {
  1526. ClusResLogSystemEventByKey(ResourceEntry->ResourceKey,
  1527. LOG_CRITICAL,
  1528. RES_SMB_SHARE_NOT_FOUND);
  1529. (g_LogEvent)(
  1530. ResourceEntry->ResourceHandle,
  1531. LOG_ERROR,
  1532. L"NERR_NetNameNotFound :share '%1!ws!' no longer exists.\n",
  1533. ResourceEntry->Params.ShareName );
  1534. success = FALSE;
  1535. } else if ( status != ERROR_SUCCESS ) {
  1536. ( void ) StringCchPrintf ( szErrorString, RTL_NUMBER_OF ( szErrorString ), L"%u", status);
  1537. ClusResLogSystemEventByKeyData1(ResourceEntry->ResourceKey,
  1538. LOG_CRITICAL,
  1539. RES_SMB_SHARE_FAILED,
  1540. sizeof(status),
  1541. &status,
  1542. szErrorString);
  1543. (g_LogEvent)(
  1544. ResourceEntry->ResourceHandle,
  1545. LOG_ERROR,
  1546. L"Error checking for share. Error %1!u!.\n",
  1547. status );
  1548. success = FALSE;
  1549. }
  1550. LeaveCriticalSection( &SmbShareLock );
  1551. if ( success ) {
  1552. NetApiBufferFree( shareInfo );
  1553. if ( IsAliveCheck ) {
  1554. HANDLE fileHandle;
  1555. WIN32_FIND_DATA fileData;
  1556. WCHAR shareName[MAX_COMPUTERNAME_LENGTH + NNLEN + SMBSHARE_EXTRA_LEN];
  1557. DWORD dwLoopCnt = 0;
  1558. ( void ) StringCchPrintf( shareName,
  1559. RTL_NUMBER_OF ( shareName ),
  1560. L"\\\\%ws\\%ws\\*.*\0",
  1561. ResourceEntry->ComputerName,
  1562. ResourceEntry->Params.ShareName );
  1563. fileHandle = FindFirstFileW( shareName,
  1564. &fileData );
  1565. //
  1566. // If we fail on the first attempt, try again. There seems to be a
  1567. // bug in the RDR where the first attempt to read a share after it
  1568. // has been deleted and reinstated. The bug is that the RDR
  1569. // returns failure on the first operation following the
  1570. // reinstatement of the share.
  1571. //
  1572. if ( fileHandle == INVALID_HANDLE_VALUE ) {
  1573. fileHandle = FindFirstFileW( shareName,
  1574. &fileData );
  1575. }
  1576. //
  1577. // If we succeeded in finding a file, or there were no files in the
  1578. // path, then return success, otherwise we had a failure.
  1579. //
  1580. status = GetLastError();
  1581. //
  1582. // Chittur Subbaraman (chitturs) - 12/6/1999
  1583. //
  1584. // If FindFirstFile returns ERROR_NETNAME_DELETED, it
  1585. // could possibly because the netname resource deletes
  1586. // all loopback sessions during the offline process. So,
  1587. // sleep and retry the call.
  1588. //
  1589. while( ( fileHandle == INVALID_HANDLE_VALUE ) &&
  1590. ( status == ERROR_NETNAME_DELETED ) &&
  1591. ( dwLoopCnt++ < 3 ) ) {
  1592. Sleep( 50 );
  1593. (g_LogEvent)(
  1594. ResourceEntry->ResourceHandle,
  1595. LOG_INFORMATION,
  1596. L"Retrying FindFirstFile on error %1!u! for share %2!ws! !\n",
  1597. status,
  1598. shareName);
  1599. fileHandle = FindFirstFileW( shareName,
  1600. &fileData );
  1601. status = GetLastError();
  1602. }
  1603. if ( (fileHandle == INVALID_HANDLE_VALUE) &&
  1604. (status != ERROR_FILE_NOT_FOUND) &&
  1605. (status != ERROR_ACCESS_DENIED) ) {
  1606. (g_LogEvent)(
  1607. ResourceEntry->ResourceHandle,
  1608. LOG_ERROR,
  1609. L"Share has gone offline, Error=%1!u! !\n",
  1610. status);
  1611. SetLastError(status);
  1612. ( void ) StringCchPrintf ( szErrorString, RTL_NUMBER_OF ( szErrorString ), L"%u", status);
  1613. ClusResLogSystemEventByKeyData1(ResourceEntry->ResourceKey,
  1614. LOG_CRITICAL,
  1615. RES_SMB_SHARE_FAILED,
  1616. sizeof(status),
  1617. &status,
  1618. szErrorString);
  1619. return(FALSE);
  1620. }
  1621. FindClose( fileHandle );
  1622. }
  1623. } else {
  1624. SetLastError(status);
  1625. }
  1626. //
  1627. // Chittur Subbaraman (chitturs) - 2/18/99
  1628. //
  1629. // If this share is a dfs root, check whether the root is still alive
  1630. //
  1631. if ( success && ResourceEntry->bDfsRootNeedsMonitoring )
  1632. {
  1633. PDFS_INFO_1 pDfsInfo1 = NULL;
  1634. WCHAR szDfsEntryPath[MAX_COMPUTERNAME_LENGTH + NNLEN + SMBSHARE_EXTRA_LEN];
  1635. //
  1636. // Prepare a path of the form \\VSName\ShareName to pass into DFS API.
  1637. //
  1638. ( void ) StringCchCopy ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\\\" );
  1639. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), ResourceEntry->szDependentNetworkName );
  1640. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\" );
  1641. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), ResourceEntry->Params.ShareName );
  1642. //
  1643. // Try to see whether the dfs root is alive.
  1644. //
  1645. status = NetDfsGetInfo( szDfsEntryPath, // Root share
  1646. NULL, // Remote server
  1647. NULL, // Remote share
  1648. 1, // Info Level
  1649. ( LPBYTE * ) &pDfsInfo1 ); // Out buffer
  1650. if ( status == NERR_Success )
  1651. {
  1652. if ( pDfsInfo1 != NULL )
  1653. {
  1654. NetApiBufferFree( pDfsInfo1 );
  1655. }
  1656. } else
  1657. {
  1658. (g_LogEvent)(
  1659. ResourceEntry->ResourceHandle,
  1660. LOG_ERROR,
  1661. L"Status of looks alive check for dfs root is %1!u! !\n",
  1662. status);
  1663. ( void ) StringCchPrintf ( szErrorString, RTL_NUMBER_OF ( szErrorString ), L"%u", status);
  1664. ClusResLogSystemEventByKeyData1(ResourceEntry->ResourceKey,
  1665. LOG_CRITICAL,
  1666. RES_SMB_SHARE_FAILED,
  1667. sizeof(status),
  1668. &status,
  1669. szErrorString);
  1670. SetLastError( status );
  1671. return( FALSE );
  1672. }
  1673. if ( IsAliveCheck )
  1674. {
  1675. //
  1676. // Make a thorough check to see whether the root share
  1677. // name matches the resource's share name.
  1678. //
  1679. status = SmbpIsDfsRoot( ResourceEntry, &success );
  1680. if ( ( status != ERROR_SUCCESS ) ||
  1681. ( success == FALSE ) )
  1682. {
  1683. (g_LogEvent)(
  1684. ResourceEntry->ResourceHandle,
  1685. LOG_ERROR,
  1686. L"Dfs root has been deleted/inaccessible, Error=%1!u! Root existence=%2!u! !\n",
  1687. status,
  1688. success);
  1689. if( status != ERROR_SUCCESS )
  1690. {
  1691. SetLastError( status );
  1692. ( void ) StringCchPrintf ( szErrorString, RTL_NUMBER_OF ( szErrorString ), L"%u", status);
  1693. ClusResLogSystemEventByKeyData1(ResourceEntry->ResourceKey,
  1694. LOG_CRITICAL,
  1695. RES_SMB_SHARE_FAILED,
  1696. sizeof(status),
  1697. &status,
  1698. szErrorString);
  1699. }
  1700. return( FALSE );
  1701. }
  1702. }
  1703. }
  1704. return(success);
  1705. } // SmbShareCheckIsAlive
  1706. BOOL
  1707. SmbShareIsAlive(
  1708. IN RESID ResourceId
  1709. )
  1710. /*++
  1711. Routine Description:
  1712. IsAlive routine for File Share resource. Also creates a
  1713. notification thread if any outstanding notifications are
  1714. present.
  1715. Arguments:
  1716. ResourceId - Supplies the resource id to be polled.
  1717. Return Value:
  1718. TRUE - Resource is alive and well
  1719. FALSE - Resource is toast.
  1720. --*/
  1721. {
  1722. PSHARE_RESOURCE resourceEntry;
  1723. DWORD status;
  1724. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  1725. if ( resourceEntry == NULL ) {
  1726. DBG_PRINT( "SmbShare: IsAlive request for a nonexistent resource id 0x%p\n",
  1727. ResourceId );
  1728. return(FALSE);
  1729. }
  1730. if ( resourceEntry->ResId != ResourceId ) {
  1731. (g_LogEvent)(
  1732. resourceEntry->ResourceHandle,
  1733. LOG_ERROR,
  1734. L"IsAlive resource sanity check failed! ResourceId = %1!u!.\n",
  1735. ResourceId );
  1736. return(FALSE);
  1737. }
  1738. #ifdef LOG_VERBOSE
  1739. (g_LogEvent)(
  1740. resourceEntry->ResourceHandle,
  1741. LOG_INFORMATION,
  1742. L"IsAlive request.\n" );
  1743. #endif
  1744. if ( ( ( resourceEntry->NotifyWorker ).hThread == NULL )
  1745. && ( resourceEntry->NotifyHandle != INVALID_HANDLE_VALUE ) )
  1746. {
  1747. //
  1748. // Chittur Subbaraman (chitturs) - 09/27/98
  1749. //
  1750. // No notify thread is active at this time (we don't want to
  1751. // deal with concurrency issues with multiple notify threads
  1752. // running concurrently since we decided to anyway use the
  1753. // rather slow approach of checking for and acting upon
  1754. // notifications within this function which may not be called
  1755. // frequently)
  1756. //
  1757. status = WaitForSingleObject( resourceEntry->NotifyHandle, 0 );
  1758. if ( status == WAIT_OBJECT_0 )
  1759. {
  1760. FindNextChangeNotification( resourceEntry->NotifyHandle );
  1761. (g_LogEvent)(
  1762. resourceEntry->ResourceHandle,
  1763. LOG_INFORMATION,
  1764. L"SmbShareIsAlive: Directory change notification received!!!\n"
  1765. );
  1766. status = ClusWorkerCreate(
  1767. &resourceEntry->NotifyWorker,
  1768. SmbpShareNotifyThread,
  1769. resourceEntry
  1770. );
  1771. if (status != ERROR_SUCCESS)
  1772. {
  1773. (g_LogEvent)(
  1774. resourceEntry->ResourceHandle,
  1775. LOG_ERROR,
  1776. L"SmbShareIsAlive: Unable to start thread for monitoring subdir creations/deletions ! ResourceId = %1!u!.\n",
  1777. resourceEntry->ResId);
  1778. }
  1779. }
  1780. }
  1781. //
  1782. // Determine if the resource is online.
  1783. //
  1784. return(SmbShareCheckIsAlive( resourceEntry, TRUE ));
  1785. } // SmbShareIsAlive
  1786. BOOL
  1787. WINAPI
  1788. SmbShareLooksAlive(
  1789. IN RESID ResourceId
  1790. )
  1791. /*++
  1792. Routine Description:
  1793. LooksAlive routine for File Share resource.
  1794. Arguments:
  1795. ResourceId - Supplies the resource id to be polled.
  1796. Return Value:
  1797. TRUE - Resource looks like it is alive and well
  1798. FALSE - Resource looks like it is toast.
  1799. --*/
  1800. {
  1801. PSHARE_RESOURCE resourceEntry;
  1802. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  1803. if ( resourceEntry == NULL ) {
  1804. DBG_PRINT( "SmbShare: LooksAlive request for a nonexistent resource id 0x%p\n",
  1805. ResourceId );
  1806. return(FALSE);
  1807. }
  1808. if ( resourceEntry->ResId != ResourceId ) {
  1809. (g_LogEvent)(
  1810. resourceEntry->ResourceHandle,
  1811. LOG_ERROR,
  1812. L"LooksAlive resource sanity check failed! ResourceId = %1!u!.\n",
  1813. ResourceId );
  1814. return(FALSE);
  1815. }
  1816. #ifdef LOG_VERBOSE
  1817. (g_LogEvent)(
  1818. resourceEntry->ResourceHandle,
  1819. LOG_INFORMATION,
  1820. L"LooksAlive request.\n" );
  1821. #endif
  1822. //
  1823. // Determine if the resource is online.
  1824. //
  1825. return(SmbShareCheckIsAlive( resourceEntry, FALSE ));
  1826. } // SmbShareLooksAlive
  1827. VOID
  1828. WINAPI
  1829. SmbShareClose(
  1830. IN RESID ResourceId
  1831. )
  1832. /*++
  1833. Routine Description:
  1834. Close routine for File Share resource.
  1835. Arguments:
  1836. ResourceId - Supplies resource id to be closed
  1837. Return Value:
  1838. None.
  1839. --*/
  1840. {
  1841. PSHARE_RESOURCE resourceEntry;
  1842. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  1843. if ( resourceEntry == NULL ) {
  1844. DBG_PRINT( "SmbShare: Close request for a nonexistent resource id 0x%p\n",
  1845. ResourceId );
  1846. return;
  1847. }
  1848. if ( resourceEntry->ResId != ResourceId ) {
  1849. (g_LogEvent)(
  1850. resourceEntry->ResourceHandle,
  1851. LOG_ERROR,
  1852. L"Close resource sanity check failed! ResourceId = %1!u!.\n",
  1853. ResourceId );
  1854. return;
  1855. }
  1856. #ifdef LOG_VERBOSE
  1857. (g_LogEvent)(
  1858. resourceEntry->ResourceHandle,
  1859. LOG_INFORMATION,
  1860. L"Close request.\n" );
  1861. #endif
  1862. //
  1863. // Chittur Subbaraman (chitturs) - 3/1/99
  1864. //
  1865. // Attempt to delete the dfs root if necessary
  1866. //
  1867. if ( resourceEntry->Params.DfsRoot ) {
  1868. NetDfsRemoveStdRoot( resourceEntry->ComputerName,
  1869. resourceEntry->Params.ShareName,
  1870. 0 );
  1871. }
  1872. //
  1873. // Close the Parameters key.
  1874. //
  1875. if ( resourceEntry->ParametersKey ) {
  1876. ClusterRegCloseKey( resourceEntry->ParametersKey );
  1877. }
  1878. if ( resourceEntry->ResourceKey ) {
  1879. ClusterRegCloseKey( resourceEntry->ResourceKey );
  1880. }
  1881. if ( resourceEntry->hResource ) {
  1882. CloseClusterResource( resourceEntry->hResource );
  1883. }
  1884. //
  1885. // Deallocate the resource entry.
  1886. //
  1887. LocalFree( resourceEntry->Params.ShareName );
  1888. LocalFree( resourceEntry->Params.Path );
  1889. LocalFree( resourceEntry->Params.Remark );
  1890. LocalFree( resourceEntry->Params.Security );
  1891. LocalFree( resourceEntry->Params.SecurityDescriptor );
  1892. LocalFree( resourceEntry );
  1893. } // SmbShareClose
  1894. DWORD
  1895. SmbShareGetRequiredDependencies(
  1896. OUT PVOID OutBuffer,
  1897. IN DWORD OutBufferSize,
  1898. OUT LPDWORD BytesReturned
  1899. )
  1900. /*++
  1901. Routine Description:
  1902. Processes the CLUSCTL_RESOURCE_GET_REQUIRED_DEPENDENCIES control function
  1903. for resources of type File Share.
  1904. Arguments:
  1905. OutBuffer - Supplies a pointer to the output buffer to be filled in.
  1906. OutBufferSize - Supplies the size, in bytes, of the available space
  1907. pointed to by OutBuffer.
  1908. BytesReturned - Returns the number of bytes of OutBuffer actually
  1909. filled in by the resource. If OutBuffer is too small, BytesReturned
  1910. contains the total number of bytes for the operation to succeed.
  1911. Return Value:
  1912. ERROR_SUCCESS - The function completed successfully.
  1913. ERROR_MORE_DATA - The output buffer is too small to return the data.
  1914. BytesReturned contains the required size.
  1915. Win32 error code - The function failed.
  1916. --*/
  1917. {
  1918. PSMB_DEPEND_SETUP pdepsetup = SmbDependSetup;
  1919. PSMB_DEPEND_DATA pdepdata = (PSMB_DEPEND_DATA)OutBuffer;
  1920. CLUSPROP_BUFFER_HELPER value;
  1921. DWORD status;
  1922. *BytesReturned = sizeof(SMB_DEPEND_DATA);
  1923. if ( OutBufferSize < sizeof(SMB_DEPEND_DATA) ) {
  1924. if ( OutBuffer == NULL ) {
  1925. status = ERROR_SUCCESS;
  1926. } else {
  1927. status = ERROR_MORE_DATA;
  1928. }
  1929. } else {
  1930. ZeroMemory( OutBuffer, sizeof(SMB_DEPEND_DATA) );
  1931. while ( pdepsetup->Syntax.dw != 0 ) {
  1932. value.pb = (PUCHAR)OutBuffer + pdepsetup->Offset;
  1933. value.pValue->Syntax.dw = pdepsetup->Syntax.dw;
  1934. value.pValue->cbLength = pdepsetup->Length;
  1935. switch ( pdepsetup->Syntax.wFormat ) {
  1936. case CLUSPROP_FORMAT_DWORD:
  1937. value.pDwordValue->dw = (DWORD)((DWORD_PTR)pdepsetup->Value);
  1938. break;
  1939. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  1940. value.pULargeIntegerValue->li.LowPart =
  1941. (DWORD)((DWORD_PTR)pdepsetup->Value);
  1942. break;
  1943. case CLUSPROP_FORMAT_SZ:
  1944. case CLUSPROP_FORMAT_EXPAND_SZ:
  1945. case CLUSPROP_FORMAT_MULTI_SZ:
  1946. case CLUSPROP_FORMAT_BINARY:
  1947. memcpy( value.pBinaryValue->rgb, pdepsetup->Value, pdepsetup->Length );
  1948. break;
  1949. default:
  1950. break;
  1951. }
  1952. pdepsetup++;
  1953. }
  1954. pdepdata->endmark.dw = CLUSPROP_SYNTAX_ENDMARK;
  1955. status = ERROR_SUCCESS;
  1956. }
  1957. return(status);
  1958. } // SmbShareGetRequiredDependencies
  1959. DWORD
  1960. DfsShareGetRequiredDependencies(
  1961. OUT PVOID OutBuffer,
  1962. IN DWORD OutBufferSize,
  1963. OUT LPDWORD BytesReturned
  1964. )
  1965. /*++
  1966. Routine Description:
  1967. Processes the CLUSCTL_RESOURCE_GET_REQUIRED_DEPENDENCIES control function
  1968. for DFS File Share resource.
  1969. Arguments:
  1970. OutBuffer - Supplies a pointer to the output buffer to be filled in.
  1971. OutBufferSize - Supplies the size, in bytes, of the available space
  1972. pointed to by OutBuffer.
  1973. BytesReturned - Returns the number of bytes of OutBuffer actually
  1974. filled in by the resource. If OutBuffer is too small, BytesReturned
  1975. contains the total number of bytes for the operation to succeed.
  1976. Return Value:
  1977. ERROR_SUCCESS - The function completed successfully.
  1978. ERROR_MORE_DATA - The output buffer is too small to return the data.
  1979. BytesReturned contains the required size.
  1980. Win32 error code - The function failed.
  1981. --*/
  1982. {
  1983. PSMB_DEPEND_SETUP pdepsetup = DfsDependSetup;
  1984. PDFS_DEPEND_DATA pdepdata = (PDFS_DEPEND_DATA)OutBuffer;
  1985. CLUSPROP_BUFFER_HELPER value;
  1986. DWORD status;
  1987. *BytesReturned = sizeof(DFS_DEPEND_DATA);
  1988. if ( OutBufferSize < sizeof(DFS_DEPEND_DATA) ) {
  1989. if ( OutBuffer == NULL ) {
  1990. status = ERROR_SUCCESS;
  1991. } else {
  1992. status = ERROR_MORE_DATA;
  1993. }
  1994. } else {
  1995. ZeroMemory( OutBuffer, sizeof(DFS_DEPEND_DATA) );
  1996. while ( pdepsetup->Syntax.dw != 0 ) {
  1997. value.pb = (PUCHAR)OutBuffer + pdepsetup->Offset;
  1998. value.pValue->Syntax.dw = pdepsetup->Syntax.dw;
  1999. value.pValue->cbLength = pdepsetup->Length;
  2000. switch ( pdepsetup->Syntax.wFormat ) {
  2001. case CLUSPROP_FORMAT_DWORD:
  2002. value.pDwordValue->dw = (DWORD)((DWORD_PTR)pdepsetup->Value);
  2003. break;
  2004. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  2005. value.pULargeIntegerValue->li.LowPart =
  2006. (DWORD)((DWORD_PTR)pdepsetup->Value);
  2007. break;
  2008. case CLUSPROP_FORMAT_SZ:
  2009. case CLUSPROP_FORMAT_EXPAND_SZ:
  2010. case CLUSPROP_FORMAT_MULTI_SZ:
  2011. case CLUSPROP_FORMAT_BINARY:
  2012. memcpy( value.pBinaryValue->rgb, pdepsetup->Value, pdepsetup->Length );
  2013. break;
  2014. default:
  2015. break;
  2016. }
  2017. pdepsetup++;
  2018. }
  2019. pdepdata->endmark.dw = CLUSPROP_SYNTAX_ENDMARK;
  2020. status = ERROR_SUCCESS;
  2021. }
  2022. return(status);
  2023. } // DfsShareGetRequiredDependencies
  2024. DWORD
  2025. SmbShareResourceControl(
  2026. IN RESID ResourceId,
  2027. IN DWORD ControlCode,
  2028. IN PVOID InBuffer,
  2029. IN DWORD InBufferSize,
  2030. OUT PVOID OutBuffer,
  2031. IN DWORD OutBufferSize,
  2032. OUT LPDWORD BytesReturned
  2033. )
  2034. /*++
  2035. Routine Description:
  2036. ResourceControl routine for File Share resources.
  2037. Perform the control request specified by ControlCode on the specified
  2038. resource.
  2039. Arguments:
  2040. ResourceId - Supplies the resource id for the specific resource.
  2041. ControlCode - Supplies the control code that defines the action
  2042. to be performed.
  2043. InBuffer - Supplies a pointer to a buffer containing input data.
  2044. InBufferSize - Supplies the size, in bytes, of the data pointed
  2045. to by InBuffer.
  2046. OutBuffer - Supplies a pointer to the output buffer to be filled in.
  2047. OutBufferSize - Supplies the size, in bytes, of the available space
  2048. pointed to by OutBuffer.
  2049. BytesReturned - Returns the number of bytes of OutBuffer actually
  2050. filled in by the resource. If OutBuffer is too small, BytesReturned
  2051. contains the total number of bytes for the operation to succeed.
  2052. Return Value:
  2053. ERROR_SUCCESS - The function completed successfully.
  2054. ERROR_RESOURCE_NOT_FOUND - RESID is not valid.
  2055. ERROR_INVALID_FUNCTION - The requested control code is not supported.
  2056. In some cases, this allows the cluster software to perform the work.
  2057. Win32 error code - The function failed.
  2058. --*/
  2059. {
  2060. DWORD status;
  2061. PSHARE_RESOURCE resourceEntry;
  2062. DWORD required;
  2063. resourceEntry = (PSHARE_RESOURCE)ResourceId;
  2064. if ( resourceEntry == NULL ) {
  2065. DBG_PRINT( "SmbShare: ResourceControl request for a nonexistent resource id 0x%p\n",
  2066. ResourceId );
  2067. return(ERROR_RESOURCE_NOT_FOUND);
  2068. }
  2069. if ( resourceEntry->ResId != ResourceId ) {
  2070. (g_LogEvent)(
  2071. resourceEntry->ResourceHandle,
  2072. LOG_ERROR,
  2073. L"ResourceControl resource sanity check failed! ResourceId = %1!u!.\n",
  2074. ResourceId );
  2075. return(ERROR_RESOURCE_NOT_FOUND);
  2076. }
  2077. #ifdef LOG_VERBOSE
  2078. (g_LogEvent)(
  2079. resourceEntry->ResourceHandle,
  2080. LOG_INFORMATION,
  2081. L"ResourceControl request.\n" );
  2082. #endif
  2083. switch ( ControlCode ) {
  2084. case CLUSCTL_RESOURCE_UNKNOWN:
  2085. *BytesReturned = 0;
  2086. status = ERROR_SUCCESS;
  2087. break;
  2088. case CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTY_FMTS:
  2089. status = ResUtilGetPropertyFormats( SmbShareResourcePrivateProperties,
  2090. OutBuffer,
  2091. OutBufferSize,
  2092. BytesReturned,
  2093. &required );
  2094. if ( status == ERROR_MORE_DATA ) {
  2095. *BytesReturned = required;
  2096. }
  2097. break;
  2098. case CLUSCTL_RESOURCE_ENUM_PRIVATE_PROPERTIES:
  2099. status = ResUtilEnumProperties( SmbShareResourcePrivateProperties,
  2100. OutBuffer,
  2101. OutBufferSize,
  2102. BytesReturned,
  2103. &required );
  2104. if ( status == ERROR_MORE_DATA ) {
  2105. *BytesReturned = required;
  2106. }
  2107. break;
  2108. case CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES:
  2109. status = SmbShareGetPrivateResProperties( resourceEntry,
  2110. OutBuffer,
  2111. OutBufferSize,
  2112. BytesReturned );
  2113. break;
  2114. case CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES:
  2115. status = SmbShareValidatePrivateResProperties( resourceEntry,
  2116. InBuffer,
  2117. InBufferSize,
  2118. NULL );
  2119. break;
  2120. case CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES:
  2121. status = SmbShareSetPrivateResProperties( resourceEntry,
  2122. InBuffer,
  2123. InBufferSize );
  2124. break;
  2125. case CLUSCTL_RESOURCE_GET_REQUIRED_DEPENDENCIES:
  2126. if ( resourceEntry->Params.DfsRoot ) {
  2127. status = DfsShareGetRequiredDependencies( OutBuffer,
  2128. OutBufferSize,
  2129. BytesReturned );
  2130. } else {
  2131. status = SmbShareGetRequiredDependencies( OutBuffer,
  2132. OutBufferSize,
  2133. BytesReturned );
  2134. }
  2135. break;
  2136. default:
  2137. status = ERROR_INVALID_FUNCTION;
  2138. break;
  2139. }
  2140. return(status);
  2141. } // SmbShareResourceControl
  2142. DWORD
  2143. SmbShareResourceTypeControl(
  2144. IN LPCWSTR ResourceTypeName,
  2145. IN DWORD ControlCode,
  2146. IN PVOID InBuffer,
  2147. IN DWORD InBufferSize,
  2148. OUT PVOID OutBuffer,
  2149. IN DWORD OutBufferSize,
  2150. OUT LPDWORD BytesReturned
  2151. )
  2152. /*++
  2153. Routine Description:
  2154. ResourceTypeControl routine for File Share resources.
  2155. Perform the control request specified by ControlCode on the specified
  2156. resource type.
  2157. Arguments:
  2158. ResourceTypeName - Supplies the name of the resource type - not useful!
  2159. ControlCode - Supplies the control code that defines the action
  2160. to be performed.
  2161. InBuffer - Supplies a pointer to a buffer containing input data.
  2162. InBufferSize - Supplies the size, in bytes, of the data pointed
  2163. to by InBuffer.
  2164. OutBuffer - Supplies a pointer to the output buffer to be filled in.
  2165. OutBufferSize - Supplies the size, in bytes, of the available space
  2166. pointed to by OutBuffer.
  2167. BytesReturned - Returns the number of bytes of OutBuffer actually
  2168. filled in by the resource. If OutBuffer is too small, BytesReturned
  2169. contains the total number of bytes for the operation to succeed.
  2170. Return Value:
  2171. ERROR_SUCCESS - The function completed successfully.
  2172. ERROR_INVALID_FUNCTION - The requested control code is not supported.
  2173. In some cases, this allows the cluster software to perform the work.
  2174. Win32 error code - The function failed.
  2175. --*/
  2176. {
  2177. DWORD status;
  2178. DWORD required;
  2179. switch ( ControlCode ) {
  2180. case CLUSCTL_RESOURCE_TYPE_UNKNOWN:
  2181. *BytesReturned = 0;
  2182. status = ERROR_SUCCESS;
  2183. break;
  2184. case CLUSCTL_RESOURCE_TYPE_GET_PRIVATE_RESOURCE_PROPERTY_FMTS:
  2185. status = ResUtilGetPropertyFormats( SmbShareResourcePrivateProperties,
  2186. OutBuffer,
  2187. OutBufferSize,
  2188. BytesReturned,
  2189. &required );
  2190. if ( status == ERROR_MORE_DATA ) {
  2191. *BytesReturned = required;
  2192. }
  2193. break;
  2194. case CLUSCTL_RESOURCE_TYPE_GET_REQUIRED_DEPENDENCIES:
  2195. // rodga 2/15/99
  2196. // CLUSBUG - how do we present DFS Root dependencies???
  2197. status = SmbShareGetRequiredDependencies( OutBuffer,
  2198. OutBufferSize,
  2199. BytesReturned );
  2200. break;
  2201. case CLUSCTL_RESOURCE_TYPE_ENUM_PRIVATE_PROPERTIES:
  2202. status = ResUtilEnumProperties( SmbShareResourcePrivateProperties,
  2203. OutBuffer,
  2204. OutBufferSize,
  2205. BytesReturned,
  2206. &required );
  2207. if ( status == ERROR_MORE_DATA ) {
  2208. *BytesReturned = required;
  2209. }
  2210. break;
  2211. case CLUSCTL_RESOURCE_TYPE_STARTING_PHASE1:
  2212. {
  2213. PCLUS_STARTING_PARAMS pStartParams;
  2214. pStartParams = ( PCLUS_STARTING_PARAMS ) InBuffer;
  2215. status = ERROR_SUCCESS;
  2216. //
  2217. // If this is a form after the first upgrade, then mark the
  2218. // DFS service as needing a recycling in the first online. We
  2219. // do this only during form since during a join, the resource
  2220. // DLL clusres.dll will get unloaded after the phase1 notification
  2221. // is dropped. So, global vars become meaningless.
  2222. //
  2223. if ( ( pStartParams->bFirst == TRUE ) &&
  2224. ( pStartParams->bForm == TRUE ) )
  2225. {
  2226. g_fDfsServiceNeedsRecyling = TRUE;
  2227. }
  2228. break;
  2229. }
  2230. case CLUSCTL_RESOURCE_TYPE_STARTING_PHASE2:
  2231. {
  2232. PCLUS_STARTING_PARAMS pStartParams;
  2233. pStartParams = ( PCLUS_STARTING_PARAMS ) InBuffer;
  2234. status = ERROR_SUCCESS;
  2235. //
  2236. // In the first join after an install, mark the dfs service as needing a
  2237. // recycle in its first online. This is done in phase 2 notification
  2238. // since clusres.dll will not get unloaded after this.
  2239. //
  2240. if ( ( pStartParams->bFirst == TRUE ) &&
  2241. ( pStartParams->bForm == FALSE ) )
  2242. {
  2243. g_fDfsServiceNeedsRecyling = TRUE;
  2244. }
  2245. break;
  2246. }
  2247. default:
  2248. status = ERROR_INVALID_FUNCTION;
  2249. break;
  2250. }
  2251. return(status);
  2252. } // SmbShareResourceTypeControl
  2253. DWORD
  2254. SmbShareGetPrivateResProperties(
  2255. IN OUT PSHARE_RESOURCE ResourceEntry,
  2256. OUT PVOID OutBuffer,
  2257. IN DWORD OutBufferSize,
  2258. OUT LPDWORD BytesReturned
  2259. )
  2260. /*++
  2261. Routine Description:
  2262. Processes the CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES control function
  2263. for resources of type SmbShare.
  2264. Arguments:
  2265. ResourceEntry - Supplies the resource entry on which to operate.
  2266. OutBuffer - Returns the output data.
  2267. OutBufferSize - Supplies the size, in bytes, of the data pointed
  2268. to by OutBuffer.
  2269. BytesReturned - The number of bytes returned in OutBuffer.
  2270. Return Value:
  2271. ERROR_SUCCESS - The function completed successfully.
  2272. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  2273. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  2274. Win32 error code - The function failed.
  2275. --*/
  2276. {
  2277. DWORD status;
  2278. DWORD required;
  2279. status = ResUtilGetAllProperties( ResourceEntry->ParametersKey,
  2280. SmbShareResourcePrivateProperties,
  2281. OutBuffer,
  2282. OutBufferSize,
  2283. BytesReturned,
  2284. &required );
  2285. if ( status == ERROR_MORE_DATA ) {
  2286. *BytesReturned = required;
  2287. }
  2288. return(status);
  2289. } // SmbShareGetPrivateResProperties
  2290. DWORD
  2291. SMBValidateUniqueProperties(
  2292. IN HRESOURCE hSelf,
  2293. IN HRESOURCE hResource,
  2294. IN PSHARE_ENUM_CONTEXT pContext
  2295. )
  2296. /*++
  2297. Routine Description:
  2298. Callback function to validate that a resource's properties are unique.
  2299. For the File Share resource the ShareName property must be unique
  2300. in the cluster.
  2301. Arguments:
  2302. hSelf - A handle to the original resource (or NULL).
  2303. hResource - A handle to a resource of the same Type. Check against this to make sure
  2304. the new properties do not conflict.
  2305. pContext - Context for the enumeration.
  2306. Return Value:
  2307. ERROR_SUCCESS - The function completed successfully, the name is unique
  2308. ERROR_DUP_NAME - The name is not unique (i.e., already claimed by another resource)
  2309. Win32 error code - The function failed.
  2310. --*/
  2311. {
  2312. DWORD dwStatus = ERROR_SUCCESS;
  2313. LPWSTR lpszShareName = NULL;
  2314. HKEY hKey = NULL;
  2315. HKEY hParamKey = NULL;
  2316. //
  2317. // If there is no share name and we are not testing a DFS root or we are testing a resource with no path, then
  2318. // we can do nothing in this call. Just return.
  2319. //
  2320. if ( ( !pContext->pParams->ShareName ) &&
  2321. ( ( !pContext->pParams->DfsRoot ) || ( !pContext->pParams->Path ) ) ) {
  2322. return( ERROR_SUCCESS );
  2323. }
  2324. // Get the share name for hResource
  2325. hKey = GetClusterResourceKey( hResource, KEY_READ );
  2326. if (!hKey) {
  2327. (g_LogEvent)(
  2328. pContext->pResourceEntry->ResourceHandle,
  2329. LOG_WARNING,
  2330. L"SMBValidateUniqueProperties: Failed to get the resource key, was resource deleted ? Error: %1!u!...\n",
  2331. GetLastError() );
  2332. return( ERROR_SUCCESS );
  2333. }
  2334. dwStatus = ClusterRegOpenKey( hKey, PARAM_KEYNAME__PARAMETERS, KEY_READ, &hParamKey );
  2335. if (dwStatus != ERROR_SUCCESS) {
  2336. (g_LogEvent)(
  2337. pContext->pResourceEntry->ResourceHandle,
  2338. LOG_WARNING,
  2339. L"SMBValidateUniqueProperties: Failed to open the cluster registry key for the resource, was resource deleted ? Error: %1!u!...\n",
  2340. dwStatus );
  2341. dwStatus = ERROR_SUCCESS;
  2342. goto error_exit;
  2343. }
  2344. lpszShareName = ResUtilGetSzValue( hParamKey, PARAM_NAME__SHARENAME );
  2345. //
  2346. // Check for uniqueness if both share names exist.
  2347. //
  2348. if ( ( lpszShareName ) &&
  2349. ( pContext->pParams->ShareName ) &&
  2350. ( !( lstrcmpiW( lpszShareName, pContext->pParams->ShareName ) ) ) ) {
  2351. (g_LogEvent)(
  2352. pContext->pResourceEntry->ResourceHandle,
  2353. LOG_ERROR,
  2354. L"SMBValidateUniqueProperties: Share name '%1' already exists.\n",
  2355. pContext->pParams->ShareName );
  2356. dwStatus = ERROR_DUP_NAME;
  2357. goto error_exit;
  2358. }
  2359. //
  2360. // If this share is set to be a DFS root share make sure there is no other DFS root
  2361. // with an overlapping path as this share.
  2362. //
  2363. if ( ( pContext->pParams->DfsRoot ) && ( pContext->pParams->Path ) )
  2364. {
  2365. DWORD dwIsDfsRoot = 0;
  2366. ResUtilGetDwordValue( hParamKey,
  2367. PARAM_NAME__DFSROOT,
  2368. &dwIsDfsRoot,
  2369. 0 );
  2370. if ( dwIsDfsRoot == 1 )
  2371. {
  2372. LPWSTR lpszPath = NULL;
  2373. WCHAR cSlash = L'\\';
  2374. lpszPath = ResUtilGetSzValue( hParamKey, PARAM_NAME__PATH );
  2375. if ( lpszPath != NULL )
  2376. {
  2377. //
  2378. // If the two paths overlap, then return failure. Note that here we make sure
  2379. // we do not flag paths such as G:\dfs1 and G:\dfs10 as overlapping, that is why we have
  2380. // the checks after the pattern matching.
  2381. //
  2382. if ( ( lstrcmp( lpszPath, pContext->pParams->Path ) == 0 )
  2383. ||
  2384. ( ( wcsstr( lpszPath, pContext->pParams->Path ) != NULL ) &&
  2385. ( lpszPath[lstrlen(pContext->pParams->Path)] == cSlash ) )
  2386. ||
  2387. ( ( ( wcsstr( pContext->pParams->Path, lpszPath ) != NULL ) &&
  2388. ( pContext->pParams->Path[lstrlen(lpszPath)] == cSlash ) ) ) )
  2389. {
  2390. dwStatus = ERROR_BAD_PATHNAME;
  2391. (g_LogEvent)(
  2392. pContext->pResourceEntry->ResourceHandle,
  2393. LOG_ERROR,
  2394. L"SMBValidateUniqueProperties: Path %1!ws! for existing DFS root %2!ws! conflicts with the specified path %3!ws! for DFS root %4!ws!...\n",
  2395. lpszPath,
  2396. (lpszShareName == NULL) ? L"NULL":lpszShareName,
  2397. pContext->pParams->Path,
  2398. (pContext->pParams->ShareName == NULL) ? L"NULL":pContext->pParams->ShareName);
  2399. }
  2400. LocalFree ( lpszPath );
  2401. }
  2402. }
  2403. }
  2404. error_exit:
  2405. if (hKey) ClusterRegCloseKey( hKey );
  2406. if (hParamKey) ClusterRegCloseKey( hParamKey );
  2407. if (lpszShareName) LocalFree( lpszShareName );
  2408. return( dwStatus );
  2409. } // SMBValidateUniqueProperties
  2410. DWORD
  2411. SmbShareValidatePrivateResProperties(
  2412. IN OUT PSHARE_RESOURCE ResourceEntry,
  2413. IN PVOID InBuffer,
  2414. IN DWORD InBufferSize,
  2415. OUT PSHARE_PARAMS Params
  2416. )
  2417. /*++
  2418. Routine Description:
  2419. Processes the CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES control
  2420. function for resources of type File Share.
  2421. Arguments:
  2422. ResourceEntry - Supplies the resource entry on which to operate.
  2423. InBuffer - Supplies a pointer to a buffer containing input data.
  2424. InBufferSize - Supplies the size, in bytes, of the data pointed
  2425. to by InBuffer.
  2426. Params - Supplies the parameter block to fill in.
  2427. Return Value:
  2428. ERROR_SUCCESS - The function completed successfully.
  2429. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  2430. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  2431. Win32 error code - The function failed.
  2432. --*/
  2433. {
  2434. DWORD status;
  2435. SHARE_PARAMS currentProps;
  2436. SHARE_PARAMS newProps;
  2437. PSHARE_PARAMS pParams = NULL;
  2438. LPWSTR nameOfPropInError;
  2439. SHARE_ENUM_CONTEXT enumContext;
  2440. //
  2441. // Check if there is input data.
  2442. //
  2443. if ( (InBuffer == NULL) ||
  2444. (InBufferSize < sizeof(DWORD)) ) {
  2445. return(ERROR_INVALID_DATA);
  2446. }
  2447. //
  2448. // Capture the current set of private properties from the registry.
  2449. //
  2450. ZeroMemory( &currentProps, sizeof(currentProps) );
  2451. status = ResUtilGetPropertiesToParameterBlock(
  2452. ResourceEntry->ParametersKey,
  2453. SmbShareResourcePrivateProperties,
  2454. (LPBYTE) &currentProps,
  2455. FALSE, /*CheckForRequiredProperties*/
  2456. &nameOfPropInError
  2457. );
  2458. if ( status != ERROR_SUCCESS ) {
  2459. (g_LogEvent)(
  2460. ResourceEntry->ResourceHandle,
  2461. LOG_ERROR,
  2462. L"Unable to read the '%1' property. Error: %2!u!.\n",
  2463. (nameOfPropInError == NULL ? L"" : nameOfPropInError),
  2464. status );
  2465. goto FnExit;
  2466. }
  2467. //
  2468. // Duplicate the resource parameter block.
  2469. //
  2470. if ( Params == NULL ) {
  2471. pParams = &newProps;
  2472. } else {
  2473. pParams = Params;
  2474. }
  2475. ZeroMemory( pParams, sizeof(SHARE_PARAMS) );
  2476. status = ResUtilDupParameterBlock( (LPBYTE) pParams,
  2477. (LPBYTE) &currentProps,
  2478. SmbShareResourcePrivateProperties );
  2479. if ( status != ERROR_SUCCESS ) {
  2480. (g_LogEvent)(
  2481. ResourceEntry->ResourceHandle,
  2482. LOG_ERROR,
  2483. L"Failed to duplicate the parameter block. Error: %1!u!.\n",
  2484. status );
  2485. return(status);
  2486. }
  2487. //
  2488. // Parse and validate the properties.
  2489. //
  2490. status = ResUtilVerifyPropertyTable( SmbShareResourcePrivateProperties,
  2491. NULL,
  2492. TRUE, // Allow unknowns
  2493. InBuffer,
  2494. InBufferSize,
  2495. (LPBYTE) pParams );
  2496. if ( status == ERROR_SUCCESS ) {
  2497. //
  2498. // Validate the path
  2499. //
  2500. if ( pParams->Path &&
  2501. !ResUtilIsPathValid( pParams->Path ) ) {
  2502. status = ERROR_INVALID_PARAMETER;
  2503. (g_LogEvent)(
  2504. ResourceEntry->ResourceHandle,
  2505. LOG_ERROR,
  2506. L"Invalid path specified ('%1'). Error: %2!u!.\n",
  2507. pParams->Path,
  2508. status );
  2509. goto FnExit;
  2510. }
  2511. //
  2512. // Validate the parameter values.
  2513. //
  2514. if ( (pParams->SecurityDescriptorSize != 0) &&
  2515. !IsValidSecurityDescriptor(pParams->SecurityDescriptor) ) {
  2516. status = ERROR_INVALID_PARAMETER;
  2517. (g_LogEvent)(
  2518. ResourceEntry->ResourceHandle,
  2519. LOG_ERROR,
  2520. L"Invalid parameter specified ('SecurityDescriptor'). Error: %1!u!.\n",
  2521. status );
  2522. goto FnExit;
  2523. }
  2524. if ( (pParams->SecuritySize != 0) &&
  2525. !IsValidSecurityDescriptor(pParams->Security) ) {
  2526. status = ERROR_INVALID_PARAMETER;
  2527. (g_LogEvent)(
  2528. ResourceEntry->ResourceHandle,
  2529. LOG_ERROR,
  2530. L"Invalid parameter specified ('Security'). Error: %1!u!.\n",
  2531. status );
  2532. goto FnExit;
  2533. }
  2534. if ( pParams->MaxUsers == 0 ) {
  2535. (g_LogEvent)(
  2536. ResourceEntry->ResourceHandle,
  2537. LOG_ERROR,
  2538. L"Invalid value for MaxUsers specified (%1!u!).\n",
  2539. pParams->MaxUsers );
  2540. status = ERROR_INVALID_PARAMETER;
  2541. goto FnExit;
  2542. }
  2543. //
  2544. // Make sure the share name is unique
  2545. //
  2546. enumContext.pResourceEntry = ResourceEntry;
  2547. enumContext.pParams = pParams;
  2548. status = ResUtilEnumResources(ResourceEntry->hResource,
  2549. CLUS_RESTYPE_NAME_FILESHR,
  2550. SMBValidateUniqueProperties,
  2551. &enumContext);
  2552. if (status != ERROR_SUCCESS) {
  2553. (g_LogEvent)(
  2554. ResourceEntry->ResourceHandle,
  2555. LOG_ERROR,
  2556. L"SmbShareValidatePrivateResProperties: ResUtilEnumResources failed with status=%1!u!...\n",
  2557. status);
  2558. goto FnExit;
  2559. }
  2560. //
  2561. // Verify that the share name is valid if one is supplied.
  2562. //
  2563. if ( pParams->ShareName )
  2564. {
  2565. status = SmbpValidateShareName( pParams->ShareName );
  2566. if (status != ERROR_SUCCESS) {
  2567. (g_LogEvent)(
  2568. ResourceEntry->ResourceHandle,
  2569. LOG_ERROR,
  2570. L"SmbShareValidatePrivateResProperties: Share name %1!ws! contains illegal chars, Status=%2!u!...\n",
  2571. pParams->ShareName,
  2572. status);
  2573. goto FnExit;
  2574. }
  2575. }
  2576. //
  2577. // Verify that the path is valid if one is supplied.
  2578. //
  2579. if ( pParams->Path )
  2580. {
  2581. //
  2582. // Verify that the directory exists.
  2583. //
  2584. if ( !ClRtlPathFileExists( pParams->Path ) ) {
  2585. status = ERROR_PATH_NOT_FOUND;
  2586. goto FnExit;
  2587. }
  2588. }
  2589. //
  2590. // If this share needs to be a DFS root, then make sure the path is on an NTFS volume.
  2591. //
  2592. if ( ( pParams->DfsRoot ) && ( pParams->Path ) )
  2593. {
  2594. WCHAR szRootPathName[4];
  2595. WCHAR szFileSystem[32]; // Array size stolen from CLUSPROP_PARTITION_INFO
  2596. //
  2597. // Copy just the drive letter from the supplied path.
  2598. //
  2599. ( void ) StringCchCopy ( szRootPathName, RTL_NUMBER_OF ( szRootPathName ), pParams->Path );
  2600. szRootPathName[2] = L'\\';
  2601. szRootPathName[3] = L'\0';
  2602. if ( !GetVolumeInformationW( szRootPathName,
  2603. NULL, // Volume name buffer
  2604. 0, // Volume name buffer size
  2605. NULL, // Volume serial number
  2606. NULL, // Maximum component length
  2607. NULL, // File system flags
  2608. szFileSystem, // File system name
  2609. sizeof(szFileSystem)/sizeof(WCHAR) ) )
  2610. {
  2611. status = GetLastError();
  2612. (g_LogEvent)(
  2613. ResourceEntry->ResourceHandle,
  2614. LOG_ERROR,
  2615. L"SmbShareValidatePrivateResProperties: GetVolumeInformation on root path %1!ws! for share %2!ws! failed, Status %3!u!...\n",
  2616. szRootPathName,
  2617. ( pParams->ShareName == NULL ) ? L"NULL":pParams->ShareName,
  2618. status );
  2619. goto FnExit;
  2620. }
  2621. if ( lstrcmpi( szFileSystem, L"NTFS" ) != 0 )
  2622. {
  2623. status = ERROR_BAD_PATHNAME;
  2624. (g_LogEvent)(
  2625. ResourceEntry->ResourceHandle,
  2626. LOG_ERROR,
  2627. L"SmbShareValidatePrivateResProperties: Root path %1!ws! for share %2!ws! is not NTFS, Status %3!u!...\n",
  2628. szRootPathName,
  2629. ( pParams->ShareName == NULL ) ? L"NULL":pParams->ShareName,
  2630. status );
  2631. goto FnExit;
  2632. }
  2633. }
  2634. } else {
  2635. (g_LogEvent)(
  2636. ResourceEntry->ResourceHandle,
  2637. LOG_ERROR,
  2638. L"Validating properties failed. Error: %1!u!.\n",
  2639. status );
  2640. }
  2641. FnExit:
  2642. //
  2643. // Cleanup our parameter block.
  2644. //
  2645. if ( ( (status != ERROR_SUCCESS)
  2646. && (pParams != NULL) )
  2647. || ( pParams == &newProps )
  2648. ) {
  2649. ResUtilFreeParameterBlock( (LPBYTE) pParams,
  2650. (LPBYTE) &currentProps,
  2651. SmbShareResourcePrivateProperties );
  2652. }
  2653. ResUtilFreeParameterBlock(
  2654. (LPBYTE) &currentProps,
  2655. NULL,
  2656. SmbShareResourcePrivateProperties
  2657. );
  2658. return(status);
  2659. } // SmbShareValidatePrivateResProperties
  2660. DWORD
  2661. SmbShareSetPrivateResProperties(
  2662. IN OUT PSHARE_RESOURCE ResourceEntry,
  2663. IN PVOID InBuffer,
  2664. IN DWORD InBufferSize
  2665. )
  2666. /*++
  2667. Routine Description:
  2668. Processes the CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES control function
  2669. for resources of type File Share.
  2670. Arguments:
  2671. ResourceEntry - Supplies the resource entry on which to operate.
  2672. InBuffer - Supplies a pointer to a buffer containing input data.
  2673. InBufferSize - Supplies the size, in bytes, of the data pointed
  2674. to by InBuffer.
  2675. Return Value:
  2676. ERROR_SUCCESS - The function completed successfully.
  2677. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  2678. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  2679. Win32 error code - The function failed.
  2680. Notes:
  2681. If the share name changes then we must delete the old share and
  2682. create a new one. Otherwise, just set the new info.
  2683. --*/
  2684. {
  2685. DWORD status;
  2686. SHARE_PARAMS params;
  2687. LPWSTR oldName = NULL;
  2688. BOOL bNameSubdirPropChange = FALSE;
  2689. BOOL bPathChanged = FALSE;
  2690. BOOL bFoundSecurity = FALSE;
  2691. BOOL bFoundSD = FALSE;
  2692. PSECURITY_DESCRIPTOR psd = NULL;
  2693. DWORD SDSize = 0;
  2694. DWORD securitySize = 0;
  2695. BOOL bChangeDfsRootProp = FALSE, bShareNameChangeAttempted = FALSE;
  2696. ZeroMemory( &params, sizeof(SHARE_PARAMS) );
  2697. //
  2698. // Parse the properties so they can be validated together.
  2699. // This routine does individual property validation.
  2700. //
  2701. status = SmbShareValidatePrivateResProperties( ResourceEntry,
  2702. InBuffer,
  2703. InBufferSize,
  2704. &params );
  2705. if ( status != ERROR_SUCCESS ) {
  2706. return(status);
  2707. }
  2708. //
  2709. // fixup the Security and Security Descriptor properties to match
  2710. //
  2711. bFoundSecurity = ( ERROR_SUCCESS == ResUtilFindBinaryProperty( InBuffer,
  2712. InBufferSize,
  2713. PARAM_NAME__SECURITY,
  2714. NULL,
  2715. &securitySize ) );
  2716. if ( bFoundSecurity && (securitySize == 0) ) {
  2717. //
  2718. // The security string could have been passed in, but it may be
  2719. // a zero length buffer. We will delete the buffer and indicate it
  2720. // is not present in that case.
  2721. //
  2722. bFoundSecurity = FALSE;
  2723. FREE_SECURITY_INFO();
  2724. }
  2725. bFoundSD =( ERROR_SUCCESS == ResUtilFindBinaryProperty( InBuffer,
  2726. InBufferSize,
  2727. PARAM_NAME__SD,
  2728. NULL,
  2729. &SDSize ) );
  2730. if ( bFoundSD && (SDSize == 0) ) {
  2731. //
  2732. // The security string could have been passed in, but it may be
  2733. // a zero length buffer. We will delete the buffer and indicate it
  2734. // is not present in that case.
  2735. //
  2736. bFoundSD = FALSE;
  2737. FREE_SECURITY_INFO();
  2738. }
  2739. if ( bFoundSD ) { // prefer SD, convert SD to Security
  2740. psd = ClRtlConvertFileShareSDToNT4Format( params.SecurityDescriptor );
  2741. //
  2742. // Bail on error
  2743. //
  2744. if ( psd == NULL ) {
  2745. status = GetLastError();
  2746. (g_LogEvent)(ResourceEntry->ResourceHandle,
  2747. LOG_ERROR,
  2748. L"Unable to convert SD to NT4 format, status %1!u!\n",
  2749. status);
  2750. ResUtilFreeParameterBlock( ( LPBYTE ) &params,
  2751. ( LPBYTE ) &ResourceEntry->Params,
  2752. SmbShareResourcePrivateProperties );
  2753. goto FnExit;
  2754. }
  2755. LocalFree( params.Security );
  2756. params.Security = psd;
  2757. params.SecuritySize = GetSecurityDescriptorLength( psd );
  2758. //
  2759. // if the ACL has changed, dump it to the cluster log
  2760. //
  2761. if ( SDSize == ResourceEntry->Params.SecurityDescriptorSize ) {
  2762. if ( memcmp(params.SecurityDescriptor,
  2763. ResourceEntry->Params.SecurityDescriptor,
  2764. SDSize ) != 0 )
  2765. {
  2766. (g_LogEvent)(ResourceEntry->ResourceHandle,
  2767. LOG_INFORMATION,
  2768. L"Changing share permissions\n");
  2769. SmbExamineSD( ResourceEntry->ResourceHandle, params.SecurityDescriptor );
  2770. }
  2771. }
  2772. }
  2773. else if ( bFoundSecurity ) { // simply write Security to SD
  2774. psd = ClRtlCopySecurityDescriptor( params.Security );
  2775. //
  2776. // Bail on error
  2777. //
  2778. if ( psd == NULL ) {
  2779. status = GetLastError();
  2780. (g_LogEvent)(ResourceEntry->ResourceHandle,
  2781. LOG_ERROR,
  2782. L"Unable to copy SD, status %1!u!\n",
  2783. status);
  2784. ResUtilFreeParameterBlock( ( LPBYTE ) &params,
  2785. ( LPBYTE ) &ResourceEntry->Params,
  2786. SmbShareResourcePrivateProperties );
  2787. goto FnExit;
  2788. }
  2789. LocalFree( params.SecurityDescriptor );
  2790. params.SecurityDescriptor = psd;
  2791. params.SecurityDescriptorSize = GetSecurityDescriptorLength( psd );
  2792. //
  2793. // if the ACL has changed, dump it to the cluster log
  2794. //
  2795. if ( securitySize == ResourceEntry->Params.SecuritySize ) {
  2796. if ( memcmp(params.Security,
  2797. ResourceEntry->Params.Security,
  2798. securitySize ) != 0 )
  2799. {
  2800. (g_LogEvent)(ResourceEntry->ResourceHandle,
  2801. LOG_INFORMATION,
  2802. L"Changing share permissions\n");
  2803. SmbExamineSD( ResourceEntry->ResourceHandle, params.Security );
  2804. }
  2805. }
  2806. }
  2807. //
  2808. // Duplicate the share name if it changed.
  2809. // Do this even if only the case of the share name changed.
  2810. //
  2811. if ( ( ResourceEntry->Params.ShareName != NULL ) &&
  2812. ( lstrcmpW( params.ShareName, ResourceEntry->Params.ShareName ) != 0 ) ) {
  2813. bShareNameChangeAttempted = TRUE;
  2814. if ( ResourceEntry->State == ClusterResourceOnline ) {
  2815. oldName = ResUtilDupString( ResourceEntry->Params.ShareName );
  2816. bNameSubdirPropChange = TRUE;
  2817. }
  2818. } else {
  2819. oldName = ResourceEntry->Params.ShareName;
  2820. }
  2821. if ( (params.HideSubDirShares != ResourceEntry->Params.HideSubDirShares) ||
  2822. (params.ShareSubDirs != ResourceEntry->Params.ShareSubDirs) ||
  2823. (params.ShareSubDirs && lstrcmpW (params.Path, ResourceEntry->Params.Path)) ) {
  2824. bNameSubdirPropChange = TRUE;
  2825. }
  2826. //
  2827. // Find out if the path changed.
  2828. //
  2829. if ( (ResourceEntry->Params.Path != NULL) &&
  2830. (lstrcmpW( params.Path, ResourceEntry->Params.Path ) != 0) ) {
  2831. bPathChanged = TRUE;
  2832. }
  2833. //
  2834. // Chittur Subbaraman (chitturs) - 2/9/99
  2835. //
  2836. // Don't welcome any changes if you are dealing with a dfs root. Also
  2837. // make sure "DfsRoot" is mutually exclusive with "ShareSubDirs"
  2838. // and "HideSubDirShares" properties.
  2839. //
  2840. if ( ( ( ResourceEntry->Params.DfsRoot ) &&
  2841. ( bNameSubdirPropChange || bPathChanged || bShareNameChangeAttempted ) ) ||
  2842. ( ( params.DfsRoot ) &&
  2843. ( params.ShareSubDirs || params.HideSubDirShares ) ) )
  2844. {
  2845. status = ERROR_RESOURCE_PROPERTY_UNCHANGEABLE;
  2846. ResUtilFreeParameterBlock( (LPBYTE) &params,
  2847. (LPBYTE) &ResourceEntry->Params,
  2848. SmbShareResourcePrivateProperties );
  2849. goto FnExit;
  2850. }
  2851. if ( params.DfsRoot && !ResourceEntry->Params.DfsRoot )
  2852. {
  2853. BOOL fIsDfsRoot = FALSE;
  2854. //
  2855. // Check if this node has a DFS root already with the same root share name. If so,
  2856. // don't allow this resource to be promoted as a DFS resource.
  2857. //
  2858. SmbpIsDfsRoot( ResourceEntry, &fIsDfsRoot );
  2859. if( fIsDfsRoot == TRUE )
  2860. {
  2861. status = ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT;
  2862. ResUtilFreeParameterBlock( (LPBYTE) &params,
  2863. (LPBYTE) &ResourceEntry->Params,
  2864. SmbShareResourcePrivateProperties );
  2865. goto FnExit;
  2866. }
  2867. }
  2868. if ( ResourceEntry->Params.DfsRoot != params.DfsRoot ) {
  2869. bChangeDfsRootProp = TRUE;
  2870. }
  2871. //
  2872. // Save the parameter values.
  2873. //
  2874. status = ResUtilSetPropertyParameterBlock( ResourceEntry->ParametersKey,
  2875. SmbShareResourcePrivateProperties,
  2876. NULL,
  2877. (LPBYTE) &params,
  2878. InBuffer,
  2879. InBufferSize,
  2880. (LPBYTE) &ResourceEntry->Params );
  2881. ResUtilFreeParameterBlock( (LPBYTE) &params,
  2882. (LPBYTE) &ResourceEntry->Params,
  2883. SmbShareResourcePrivateProperties );
  2884. //
  2885. // If the resource is online, set the new values. If online pending,
  2886. // we must wait until the user brings it online again.
  2887. //
  2888. if ( status == ERROR_SUCCESS ) {
  2889. if ( (ResourceEntry->State == ClusterResourceOnline) && !bNameSubdirPropChange && !bPathChanged ) {
  2890. PSHARE_INFO_502 oldShareInfo;
  2891. SHARE_INFO_502 newShareInfo;
  2892. EnterCriticalSection( &SmbShareLock );
  2893. // Get current information.
  2894. status = NetShareGetInfo( NULL,
  2895. oldName,
  2896. 502,
  2897. (LPBYTE*)&oldShareInfo );
  2898. if ( status == ERROR_SUCCESS ) {
  2899. DWORD invalidParam;
  2900. //
  2901. // Set new share info.
  2902. //
  2903. CopyMemory( &newShareInfo, oldShareInfo, sizeof( newShareInfo ) );
  2904. newShareInfo.shi502_netname = ResourceEntry->Params.ShareName;
  2905. newShareInfo.shi502_remark = ResourceEntry->Params.Remark;
  2906. newShareInfo.shi502_max_uses = ResourceEntry->Params.MaxUsers;
  2907. newShareInfo.shi502_path = ResourceEntry->Params.Path;
  2908. newShareInfo.shi502_security_descriptor = ResourceEntry->Params.SecurityDescriptor;
  2909. //
  2910. // Set new info.
  2911. //
  2912. status = NetShareSetInfo( NULL,
  2913. oldName,
  2914. 502,
  2915. (LPBYTE)&newShareInfo,
  2916. &invalidParam );
  2917. if ( status != ERROR_SUCCESS ) {
  2918. (g_LogEvent)(
  2919. ResourceEntry->ResourceHandle,
  2920. LOG_ERROR,
  2921. L"SetPrivateProps, error setting info on share '%1!ws!. Error %2!u!, property # %3!d!.\n",
  2922. oldName,
  2923. status,
  2924. invalidParam );
  2925. status = ERROR_RESOURCE_PROPERTIES_STORED;
  2926. }
  2927. NetApiBufferFree( oldShareInfo );
  2928. if ( (status == ERROR_SUCCESS) ||
  2929. (status == ERROR_RESOURCE_PROPERTIES_STORED) ) {
  2930. status = SmbpSetCacheFlags( ResourceEntry,
  2931. ResourceEntry->Params.ShareName );
  2932. if ( status != ERROR_SUCCESS ) {
  2933. status = ERROR_RESOURCE_PROPERTIES_STORED;
  2934. }
  2935. }
  2936. } else {
  2937. (g_LogEvent)(
  2938. ResourceEntry->ResourceHandle,
  2939. LOG_ERROR,
  2940. L"SetPrivateProps, error getting info on share '%1!ws!. Error %2!u!.\n",
  2941. oldName,
  2942. status );
  2943. status = ERROR_RESOURCE_PROPERTIES_STORED;
  2944. }
  2945. LeaveCriticalSection( &SmbShareLock );
  2946. } else if ( (ResourceEntry->State == ClusterResourceOnlinePending) ||
  2947. (ResourceEntry->State == ClusterResourceOnline) ) {
  2948. status = ERROR_RESOURCE_PROPERTIES_STORED;
  2949. }
  2950. }
  2951. FnExit:
  2952. if ( oldName != ResourceEntry->Params.ShareName ) {
  2953. LocalFree( oldName );
  2954. }
  2955. if ( ( status == ERROR_SUCCESS ) && bChangeDfsRootProp ) {
  2956. if ( (ResourceEntry->State == ClusterResourceOnlinePending) ||
  2957. (ResourceEntry->State == ClusterResourceOnline) ) {
  2958. status = ERROR_RESOURCE_PROPERTIES_STORED;
  2959. }
  2960. }
  2961. return(status);
  2962. } // SmbShareSetPrivateResProperties
  2963. DWORD
  2964. SmbpHandleDfsRoot(
  2965. IN PSHARE_RESOURCE pResourceEntry,
  2966. OUT PBOOL pbIsExistingDfsRoot
  2967. )
  2968. /*++
  2969. Routine Description:
  2970. Handles an smbshare which is configured as a DFS root.
  2971. Arguments:
  2972. pResourceEntry - Supplies the pointer to the resource block
  2973. pbIsExistingDfsRoot - Specifies whether the dfs root is a wolfpack resource
  2974. Return Value:
  2975. None.
  2976. --*/
  2977. {
  2978. DWORD dwStatus = ERROR_SUCCESS;
  2979. DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  2980. BOOL fStatus;
  2981. LPWSTR lpszDfsRootCheckpointName = NULL;
  2982. //
  2983. // Recycle the DFS service if this is the first online after an install. This must be
  2984. // done before calling GetDfsRootMetadataLocation since in a W2K-Windows Server 2003 cluster on the first
  2985. // failover from W2K to Windows Server 2003, the DFS service needs to migrate the W2K root to Windows Server
  2986. // 2003 location and that happens during a restart. Only after that migration, the GetDfsRootMetadataLocation
  2987. // will find the right data in the Windows Server 2003 location.
  2988. //
  2989. //
  2990. if ( pResourceEntry->Params.DfsRoot )
  2991. {
  2992. dwStatus = SmbpRecycleDfsService( pResourceEntry );
  2993. if ( dwStatus != ERROR_SUCCESS )
  2994. {
  2995. (g_LogEvent)(
  2996. pResourceEntry->ResourceHandle,
  2997. LOG_ERROR,
  2998. L"SmbpHandleDfsRoot: Unable to recycle DFS service for root %1!ws!, status %2!u!\n",
  2999. pResourceEntry->Params.ShareName,
  3000. dwStatus);
  3001. goto FnExit;
  3002. }
  3003. }
  3004. //
  3005. // Check whether this resource represents an existing dfs root. Note that you cannot use
  3006. // SmbpIsDfsRoot here since that function only assuredly returns roots that are MASTER
  3007. // in this node. Those roots that are STANDBY may fail to come out of NetDfsEnum if a
  3008. // checkpoint restore is in progress at the time we invoke the enum.
  3009. //
  3010. // This is a private API provided by UDAYH of DFS team on 4/26/2001.
  3011. //
  3012. dwStatus = GetDfsRootMetadataLocation( pResourceEntry->Params.ShareName,
  3013. &lpszDfsRootCheckpointName );
  3014. if ( dwStatus == ERROR_NOT_FOUND )
  3015. {
  3016. *pbIsExistingDfsRoot = FALSE;
  3017. //
  3018. // Change status to success so that you return the right status from this function if
  3019. // you happen to bail out early.
  3020. //
  3021. dwStatus = ERROR_SUCCESS;
  3022. (g_LogEvent)(
  3023. pResourceEntry->ResourceHandle,
  3024. LOG_INFORMATION,
  3025. L"SmbpHandleDfsRoot: DFS root %1!ws! NOT found in local node...\n",
  3026. pResourceEntry->Params.ShareName);
  3027. } else if ( dwStatus == ERROR_SUCCESS )
  3028. {
  3029. *pbIsExistingDfsRoot = TRUE;
  3030. (g_LogEvent)(
  3031. pResourceEntry->ResourceHandle,
  3032. LOG_INFORMATION,
  3033. L"SmbpHandleDfsRoot: DFS root %1!ws! found in local node...\n",
  3034. pResourceEntry->Params.ShareName);
  3035. } else
  3036. {
  3037. (g_LogEvent)(
  3038. pResourceEntry->ResourceHandle,
  3039. LOG_ERROR,
  3040. L"SmbpHandleDfsRoot: GetDfsRootMetadataLocation(1) for DFS root '%1!ws!' returns %2!u!...\n",
  3041. pResourceEntry->Params.ShareName,
  3042. dwStatus);
  3043. goto FnExit;
  3044. }
  3045. //
  3046. // If there is a DFS root on this node that matches the share name of this resource or if
  3047. // the user is attempting to set up a DFS root, then get the VS name that provides for
  3048. // this resource so that we can pass it onto DFS APIs.
  3049. //
  3050. if ( ( pResourceEntry->Params.DfsRoot ) ||
  3051. ( *pbIsExistingDfsRoot == TRUE ) )
  3052. {
  3053. //
  3054. // Get the dependent network name of the dfs root resource. You need to do this in
  3055. // every online to account for the dependency change while this resource was offline.
  3056. //
  3057. fStatus = GetClusterResourceNetworkName( pResourceEntry->hResource,
  3058. pResourceEntry->szDependentNetworkName,
  3059. &dwSize );
  3060. if ( !fStatus )
  3061. {
  3062. dwStatus = GetLastError();
  3063. (g_LogEvent)(
  3064. pResourceEntry->ResourceHandle,
  3065. LOG_ERROR,
  3066. L"SmbpHandleDfsRoot: GetClusterResourceNetworkName for share %1!ws! returns %2!u!...\n",
  3067. pResourceEntry->Params.ShareName,
  3068. dwStatus);
  3069. goto FnExit;
  3070. }
  3071. (g_LogEvent)(
  3072. pResourceEntry->ResourceHandle,
  3073. LOG_INFORMATION,
  3074. L"SmbpHandleDfsRoot: DFS root share %1!ws! has a provider VS name of %2!ws!...\n",
  3075. pResourceEntry->Params.ShareName,
  3076. pResourceEntry->szDependentNetworkName);
  3077. //
  3078. // HACKHACK: Chittur Subbaraman (chitturs) - 5/18/2001
  3079. //
  3080. // Sleep for few secs to mask an issue with the dependent netname not being really usable
  3081. // (especially as binding parameter to named pipes done by the DFS APIs we call below) after
  3082. // it declares itself to be online. This is due to the fact that netname NBT
  3083. // registrations are apparently async and it takes a while for that to percolate to other
  3084. // drivers such as SRV.
  3085. //
  3086. Sleep ( 4 * 1000 );
  3087. }
  3088. if ( !pResourceEntry->Params.DfsRoot )
  3089. {
  3090. if ( *pbIsExistingDfsRoot )
  3091. {
  3092. //
  3093. // This means the user no longer wants the share to be a
  3094. // DFS root. Delete the registry checkpoints and the
  3095. // corresponding DFS root.
  3096. //
  3097. dwStatus = SmbpDeleteDfsRoot( pResourceEntry );
  3098. if ( dwStatus != ERROR_SUCCESS )
  3099. {
  3100. (g_LogEvent)(
  3101. pResourceEntry->ResourceHandle,
  3102. LOG_ERROR,
  3103. L"SmbpHandleDfsRoot: Failed to delete DFS root for share %1!ws!, status %2!u!...\n",
  3104. pResourceEntry->Params.ShareName,
  3105. dwStatus);
  3106. goto FnExit;
  3107. }
  3108. *pbIsExistingDfsRoot = FALSE;
  3109. }
  3110. pResourceEntry->bDfsRootNeedsMonitoring = FALSE;
  3111. goto FnExit;
  3112. }
  3113. //
  3114. // If there is no DFS root with the same rootshare name
  3115. // as this resource, attempt to create the dfs root. However, the
  3116. // user could have mistakenly created a dfs root with a different
  3117. // share name. In such a case, the following create call will fail.
  3118. //
  3119. if ( !( *pbIsExistingDfsRoot ) )
  3120. {
  3121. dwStatus = SmbpCreateDfsRoot( pResourceEntry );
  3122. if ( dwStatus != ERROR_SUCCESS )
  3123. {
  3124. (g_LogEvent)(
  3125. pResourceEntry->ResourceHandle,
  3126. LOG_ERROR,
  3127. L"SmbpHandleDfsRoot: Create dfs root for share %1!ws! returns %2!u!...\n",
  3128. pResourceEntry->Params.ShareName,
  3129. dwStatus);
  3130. if ( dwStatus == ERROR_FILE_EXISTS )
  3131. {
  3132. dwStatus = ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT;
  3133. }
  3134. ClusResLogSystemEventByKeyData( pResourceEntry->ResourceKey,
  3135. LOG_CRITICAL,
  3136. RES_SMB_CANT_CREATE_DFS_ROOT,
  3137. sizeof( dwStatus ),
  3138. &dwStatus );
  3139. goto FnExit;
  3140. }
  3141. (g_LogEvent)(
  3142. pResourceEntry->ResourceHandle,
  3143. LOG_INFORMATION,
  3144. L"SmbpHandleDfsRoot: Create dfs root for share %1!ws!\n",
  3145. pResourceEntry->Params.ShareName);
  3146. *pbIsExistingDfsRoot = TRUE;
  3147. }
  3148. if ( lpszDfsRootCheckpointName == NULL )
  3149. {
  3150. dwStatus = GetDfsRootMetadataLocation( pResourceEntry->Params.ShareName,
  3151. &lpszDfsRootCheckpointName );
  3152. if ( dwStatus != ERROR_SUCCESS )
  3153. {
  3154. (g_LogEvent)(
  3155. pResourceEntry->ResourceHandle,
  3156. LOG_ERROR,
  3157. L"SmbpHandleDfsRoot: GetDfsRootMetadataLocation(2) for dfs root %1!ws!, status %2!u!...\n",
  3158. pResourceEntry->Params.ShareName,
  3159. dwStatus);
  3160. goto FnExit;
  3161. }
  3162. }
  3163. (g_LogEvent)(
  3164. pResourceEntry->ResourceHandle,
  3165. LOG_INFORMATION,
  3166. L"SmbpHandleDfsRoot: Dfs root %1!ws! metadata location from DFS API is %2!ws!...\n",
  3167. pResourceEntry->Params.ShareName,
  3168. lpszDfsRootCheckpointName);
  3169. dwStatus = ClusterResourceControl(
  3170. pResourceEntry->hResource,
  3171. NULL,
  3172. CLUSCTL_RESOURCE_ADD_REGISTRY_CHECKPOINT,
  3173. lpszDfsRootCheckpointName,
  3174. (lstrlenW(lpszDfsRootCheckpointName) + 1) * sizeof(WCHAR),
  3175. NULL,
  3176. 0,
  3177. &dwSize );
  3178. if ( dwStatus != ERROR_SUCCESS )
  3179. {
  3180. if ( dwStatus == ERROR_ALREADY_EXISTS )
  3181. {
  3182. dwStatus = ERROR_SUCCESS;
  3183. }
  3184. else
  3185. {
  3186. (g_LogEvent)(
  3187. pResourceEntry->ResourceHandle,
  3188. LOG_ERROR,
  3189. L"SmbpHandleDfsRoot: Failed to set registry checkpoint %1!ws! for share %2!ws!, status %3!u!...\n",
  3190. lpszDfsRootCheckpointName,
  3191. pResourceEntry->Params.ShareName,
  3192. dwStatus);
  3193. }
  3194. }
  3195. pResourceEntry->bDfsRootNeedsMonitoring = TRUE;
  3196. FnExit:
  3197. //
  3198. // Free memory for the checkpoint name buffer for this DFS root resource. This is a private API provided
  3199. // by UDAYH of DFS team on 4/26/2001.
  3200. //
  3201. if ( lpszDfsRootCheckpointName != NULL )
  3202. ReleaseDfsRootMetadataLocation ( lpszDfsRootCheckpointName );
  3203. return( dwStatus );
  3204. } // SmbpHandleDfsRoot
  3205. DWORD
  3206. SmbpIsDfsRoot(
  3207. IN PSHARE_RESOURCE pResourceEntry,
  3208. OUT PBOOL pbIsDfsRoot
  3209. )
  3210. /*++
  3211. Routine Description:
  3212. Checks if this root share is a dfs root.
  3213. Arguments:
  3214. pResourceEntry - Supplies the pointer to the resource block
  3215. pbIsDfsRoot - Specifies whether a dfs root with the same root share
  3216. name as this resource exists.
  3217. Return Value:
  3218. ERROR_SUCCESS or a Win32 error code
  3219. --*/
  3220. {
  3221. DWORD dwStatus = ERROR_SUCCESS;
  3222. PDFS_INFO_300 pDfsInfo300 = NULL, pTemp = NULL;
  3223. DWORD cEntriesRead = 0;
  3224. DWORD dwResume = 0, i;
  3225. LPWSTR pLastSlash = NULL;
  3226. WCHAR cSlash = L'\\';
  3227. //
  3228. // Chittur Subbaraman (chitturs) - 4/14/2001
  3229. //
  3230. *pbIsDfsRoot = FALSE;
  3231. //
  3232. // Call the NetDfsEnum function specifying level 200.
  3233. //
  3234. dwStatus = NetDfsEnum( pResourceEntry->ComputerName, // Local computer name
  3235. 300, // Info level
  3236. 0xFFFFFFFF, // Return all info
  3237. ( LPBYTE * ) &pDfsInfo300, // Data buffer
  3238. &cEntriesRead, // Entries read
  3239. &dwResume ); // Resume handle
  3240. if ( dwStatus != ERROR_SUCCESS )
  3241. {
  3242. //
  3243. // If we did not find any root return success
  3244. //
  3245. if ( dwStatus == ERROR_FILE_NOT_FOUND )
  3246. {
  3247. dwStatus = ERROR_SUCCESS;
  3248. } else
  3249. {
  3250. (g_LogEvent)(
  3251. pResourceEntry->ResourceHandle,
  3252. LOG_ERROR,
  3253. L"SmbpIsDfsRoot: NetDfsEnum returns %1!u! for root share %2!ws!...\n",
  3254. dwStatus,
  3255. pResourceEntry->Params.ShareName);
  3256. }
  3257. goto FnExit;
  3258. }
  3259. pTemp = pDfsInfo300;
  3260. //
  3261. // The enumerated roots will be of the form \server\rootname, so you need to check for the
  3262. // name after the last \ coming out of the enum.
  3263. //
  3264. for( i=0; i<cEntriesRead; i++, pTemp++ )
  3265. {
  3266. pLastSlash = wcsrchr( pTemp->DfsName, cSlash );
  3267. if ( pLastSlash == NULL ) continue;
  3268. if ( lstrcmp( pResourceEntry->Params.ShareName, pLastSlash+1 ) == 0 )
  3269. {
  3270. *pbIsDfsRoot = TRUE;
  3271. break;
  3272. }
  3273. } // for
  3274. //
  3275. // Free the allocated buffer.
  3276. //
  3277. NetApiBufferFree( pDfsInfo300 );
  3278. FnExit:
  3279. return( dwStatus );
  3280. } // SmbpIsDfsRoot
  3281. DWORD
  3282. SmbpPrepareOnlineDfsRoot(
  3283. IN PSHARE_RESOURCE ResourceEntry
  3284. )
  3285. /*++
  3286. Routine Description:
  3287. Prepares the online of the dfs root share.
  3288. Arguments:
  3289. ResourceEntry - Supplies the pointer to the resource block
  3290. Return Value:
  3291. ERROR_SUCCESS on success
  3292. Win32 error code otherwise
  3293. --*/
  3294. {
  3295. DWORD dwStatus;
  3296. DFS_INFO_101 dfsInfo101;
  3297. WCHAR szDfsEntryPath[MAX_COMPUTERNAME_LENGTH + NNLEN + SMBSHARE_EXTRA_LEN];
  3298. //
  3299. // Make sure the DFS service is started. This is necessary since the cluster service does not set
  3300. // an explicit dependency on DFS service.
  3301. //
  3302. dwStatus = ResUtilStartResourceService( DFS_SVCNAME,
  3303. NULL );
  3304. if ( dwStatus != ERROR_SUCCESS )
  3305. {
  3306. (g_LogEvent)(
  3307. ResourceEntry->ResourceHandle,
  3308. LOG_ERROR,
  3309. L"SmbpPrepareOnlineDfsRoot: Failed to start DFS service, share name %1!ws!, status %2!u!...\n",
  3310. ResourceEntry->Params.ShareName,
  3311. dwStatus);
  3312. goto FnExit;
  3313. }
  3314. dfsInfo101.State = DFS_VOLUME_STATE_RESYNCHRONIZE;
  3315. //
  3316. // Prepare a path of the form \\VSName\ShareName to pass into DFS API.
  3317. //
  3318. ( void ) StringCchCopy ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\\\" );
  3319. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), ResourceEntry->szDependentNetworkName );
  3320. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\" );
  3321. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), ResourceEntry->Params.ShareName );
  3322. dwStatus = NetDfsSetInfo( szDfsEntryPath, // Root share
  3323. NULL, // Remote server name
  3324. NULL, // Remote share name
  3325. 101, // Info level
  3326. ( PBYTE ) &dfsInfo101 ); // Input buffer
  3327. if ( dwStatus != ERROR_SUCCESS )
  3328. {
  3329. (g_LogEvent)(
  3330. ResourceEntry->ResourceHandle,
  3331. LOG_ERROR,
  3332. L"SmbpPrepareOnlineDfsRoot: Failed to set DFS info for root %1!ws!, status %2!u!...\n",
  3333. ResourceEntry->Params.ShareName,
  3334. dwStatus);
  3335. ClusResLogSystemEventByKeyData( ResourceEntry->ResourceKey,
  3336. LOG_CRITICAL,
  3337. RES_SMB_CANT_INIT_DFS_SVC,
  3338. sizeof( dwStatus ),
  3339. &dwStatus );
  3340. goto FnExit;
  3341. }
  3342. //
  3343. // HACKHACK (chitturs) - 5/21/2001
  3344. //
  3345. // FFF in liveness check returns ERROR_PATH_NOT_FOUND in the first liveness check after
  3346. // online. This is due to the fact that the RDR caches share info for 10 seconds after
  3347. // share creation and if the cache is not invalidated by the time we call FFF, RDR gets confused.
  3348. //
  3349. Sleep( 12 * 1000 );
  3350. FnExit:
  3351. return( dwStatus );
  3352. } // SmbpPrepareOnlineDfsRoot
  3353. DWORD
  3354. SmbpCreateDfsRoot(
  3355. IN PSHARE_RESOURCE pResourceEntry
  3356. )
  3357. /*++
  3358. Routine Description:
  3359. Create a DFS root.
  3360. Arguments:
  3361. pResourceEntry - Supplies the pointer to the resource block
  3362. Return Value:
  3363. ERROR_SUCCESS on success, a Win32 error code otherwise.
  3364. --*/
  3365. {
  3366. DWORD dwStatus = ERROR_SUCCESS;
  3367. //
  3368. // Make sure the DFS service is started. This is necessary since the cluster service does not set
  3369. // an explicit dependency on DFS service.
  3370. //
  3371. dwStatus = ResUtilStartResourceService( DFS_SVCNAME,
  3372. NULL );
  3373. if ( dwStatus != ERROR_SUCCESS )
  3374. {
  3375. (g_LogEvent)(
  3376. pResourceEntry->ResourceHandle,
  3377. LOG_ERROR,
  3378. L"SmbpCreateDfsRoot: Failed to start DFS service, share name %1!ws!, status %2!u!...\n",
  3379. pResourceEntry->Params.ShareName,
  3380. dwStatus);
  3381. goto FnExit;
  3382. }
  3383. //
  3384. // Chittur Subbaraman (chitturs) - 2/14/99
  3385. //
  3386. dwStatus = NetDfsAddStdRoot( pResourceEntry->szDependentNetworkName,
  3387. pResourceEntry->Params.ShareName,
  3388. NULL,
  3389. 0 );
  3390. if ( dwStatus != ERROR_SUCCESS )
  3391. {
  3392. (g_LogEvent)(
  3393. pResourceEntry->ResourceHandle,
  3394. LOG_ERROR,
  3395. L"SmbpCreateDfsRoot: Failed to create dfs root for share %1!ws!, status %2!u!...\n",
  3396. pResourceEntry->Params.ShareName,
  3397. dwStatus);
  3398. goto FnExit;
  3399. }
  3400. FnExit:
  3401. return ( dwStatus );
  3402. } // SmbpCreateDfsRoot
  3403. DWORD
  3404. SmbpDeleteDfsRoot(
  3405. IN PSHARE_RESOURCE pResourceEntry
  3406. )
  3407. /*++
  3408. Routine Description:
  3409. Delete the DFS root and the registry checkpoints.
  3410. Arguments:
  3411. pResourceEntry - Supplies the pointer to the resource block
  3412. Return Value:
  3413. ERROR_SUCCESS on success, a Win32 error code otherwise.
  3414. --*/
  3415. {
  3416. DWORD dwStatus = ERROR_SUCCESS;
  3417. DWORD dwReturnSize;
  3418. LPWSTR lpszDfsRootCheckpointName = NULL;
  3419. //
  3420. // Get the checkpoint name for this DFS root resource. This is a private API provided
  3421. // by UDAYH of DFS team on 4/26/2001.
  3422. //
  3423. dwStatus = GetDfsRootMetadataLocation( pResourceEntry->Params.ShareName,
  3424. &lpszDfsRootCheckpointName );
  3425. if ( dwStatus != ERROR_SUCCESS )
  3426. {
  3427. (g_LogEvent)(
  3428. pResourceEntry->ResourceHandle,
  3429. LOG_ERROR,
  3430. L"SmbpDeleteDfsRoot: Failed to get metadata location for dfs root %1!ws!, status %2!u!...\n",
  3431. pResourceEntry->Params.ShareName,
  3432. dwStatus);
  3433. goto FnExit;
  3434. }
  3435. (g_LogEvent)(
  3436. pResourceEntry->ResourceHandle,
  3437. LOG_INFORMATION,
  3438. L"SmbpDeleteDfsRoot: Dfs root %1!ws! metadata location from DFS API is %2!ws!...\n",
  3439. pResourceEntry->Params.ShareName,
  3440. lpszDfsRootCheckpointName);
  3441. dwStatus = ClusterResourceControl(
  3442. pResourceEntry->hResource,
  3443. NULL,
  3444. CLUSCTL_RESOURCE_DELETE_REGISTRY_CHECKPOINT,
  3445. lpszDfsRootCheckpointName,
  3446. (lstrlenW(lpszDfsRootCheckpointName) + 1) * sizeof(WCHAR),
  3447. NULL,
  3448. 0,
  3449. &dwReturnSize );
  3450. if ( dwStatus != ERROR_SUCCESS )
  3451. {
  3452. if ( dwStatus == ERROR_FILE_NOT_FOUND )
  3453. {
  3454. dwStatus = ERROR_SUCCESS;
  3455. } else
  3456. {
  3457. (g_LogEvent)(
  3458. pResourceEntry->ResourceHandle,
  3459. LOG_ERROR,
  3460. L"SmbpDeleteDfsRoot: Failed to delete registry checkpoint %1!ws! for share %2!ws!, status %3!u!...\n",
  3461. lpszDfsRootCheckpointName,
  3462. pResourceEntry->Params.ShareName,
  3463. dwStatus);
  3464. goto FnExit;
  3465. }
  3466. }
  3467. //
  3468. // Make sure the DFS service is started. This is necessary since the cluster service does not set
  3469. // an explicit dependency on DFS service.
  3470. //
  3471. dwStatus = ResUtilStartResourceService( DFS_SVCNAME,
  3472. NULL );
  3473. if ( dwStatus != ERROR_SUCCESS )
  3474. {
  3475. (g_LogEvent)(
  3476. pResourceEntry->ResourceHandle,
  3477. LOG_ERROR,
  3478. L"SmbpDeleteDfsRoot: Failed to start DFS service, share name %1!ws!, status %2!u!...\n",
  3479. pResourceEntry->Params.ShareName,
  3480. dwStatus);
  3481. goto FnExit;
  3482. }
  3483. dwStatus = NetDfsRemoveStdRoot( pResourceEntry->szDependentNetworkName,
  3484. pResourceEntry->Params.ShareName,
  3485. 0 );
  3486. if ( dwStatus != ERROR_SUCCESS )
  3487. {
  3488. (g_LogEvent)(
  3489. pResourceEntry->ResourceHandle,
  3490. LOG_ERROR,
  3491. L"SmbpDeleteDfsRoot: Failed to delete dfs root %1!ws!, status %2!u!...\n",
  3492. pResourceEntry->Params.ShareName,
  3493. dwStatus);
  3494. goto FnExit;
  3495. } else
  3496. {
  3497. (g_LogEvent)(
  3498. pResourceEntry->ResourceHandle,
  3499. LOG_ERROR,
  3500. L"SmbpDeleteDfsRoot: Delete share %1!ws! as a dfs root\n",
  3501. pResourceEntry->Params.ShareName);
  3502. }
  3503. FnExit:
  3504. //
  3505. // Free memory for the checkpoint name buffer for this DFS root resource. This is a private API provided
  3506. // by UDAYH of DFS team on 4/26/2001.
  3507. //
  3508. if ( lpszDfsRootCheckpointName != NULL )
  3509. ReleaseDfsRootMetadataLocation ( lpszDfsRootCheckpointName );
  3510. return ( dwStatus );
  3511. } // SmbpDeleteDfsRoot
  3512. DWORD
  3513. SmbpResetDfs(
  3514. IN PSHARE_RESOURCE pResourceEntry
  3515. )
  3516. /*++
  3517. Routine Description:
  3518. Set the DFS root to standby mode. This will make the root inaccessible as well as allow the
  3519. share to be deleted.
  3520. Arguments:
  3521. pResourceEntry - Supplies the pointer to the resource block
  3522. Return Value:
  3523. ERROR_SUCCESS on success, a Win32 error code otherwise.
  3524. --*/
  3525. {
  3526. DFS_INFO_101 dfsInfo101;
  3527. WCHAR szDfsEntryPath[MAX_COMPUTERNAME_LENGTH + NNLEN + SMBSHARE_EXTRA_LEN];
  3528. DWORD dwStatus;
  3529. WCHAR szNetworkName[MAX_COMPUTERNAME_LENGTH+1];
  3530. dfsInfo101.State = DFS_VOLUME_STATE_STANDBY;
  3531. //
  3532. // If this function is invoked from SmbShareOnlineThread, we would not have saved the dependent
  3533. // network name yet into the resource structure, that happens later in SmbpHandleDfsRoot when
  3534. // we are sure that we are talking about a DFS root share. Note that we cannot be sure in the online thread
  3535. // if a dependent network name even exists. For such cases, use the computer name as parameter to the DFS API.
  3536. //
  3537. if ( pResourceEntry->szDependentNetworkName[0] == L'\0' )
  3538. {
  3539. ( void ) StringCchCopy ( szNetworkName, RTL_NUMBER_OF ( szNetworkName ), pResourceEntry->ComputerName );
  3540. } else
  3541. {
  3542. ( void ) StringCchCopy ( szNetworkName, RTL_NUMBER_OF ( szNetworkName ), pResourceEntry->szDependentNetworkName );
  3543. }
  3544. //
  3545. // Prepare a path of the form \\NetworkName\ShareName to pass into DFS API.
  3546. //
  3547. ( void ) StringCchCopy ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\\\" );
  3548. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), szNetworkName );
  3549. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\" );
  3550. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), pResourceEntry->Params.ShareName );
  3551. dwStatus = NetDfsSetInfo( szDfsEntryPath, // Root share
  3552. NULL, // Remote server name
  3553. NULL, // Remote share name
  3554. 101, // Info level
  3555. ( PBYTE ) &dfsInfo101 ); // Input buffer
  3556. if ( dwStatus != ERROR_SUCCESS )
  3557. {
  3558. (g_LogEvent)(
  3559. pResourceEntry->ResourceHandle,
  3560. LOG_ERROR,
  3561. L"SmbpResetDfs: NetDfsSetInfo with VS name %1!ws! for root %2!ws!, status %3!u!...\n",
  3562. szNetworkName,
  3563. pResourceEntry->Params.ShareName,
  3564. dwStatus);
  3565. //
  3566. // If this function was called as a part of resmon rundown, then it is possible that
  3567. // the VS is terminated by resmon before this call is made. In such a case, we would
  3568. // fail in the above call. So, retry using computer name. That should succeed.
  3569. //
  3570. // Prepare a path of the form \\ComputerName\ShareName to pass into DFS API.
  3571. //
  3572. ( void ) StringCchCopy ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\\\" );
  3573. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), pResourceEntry->ComputerName );
  3574. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), L"\\" );
  3575. ( void ) StringCchCat ( szDfsEntryPath, RTL_NUMBER_OF ( szDfsEntryPath ), pResourceEntry->Params.ShareName );
  3576. dwStatus = NetDfsSetInfo( szDfsEntryPath, // Root share
  3577. NULL, // Remote server name
  3578. NULL, // Remote share name
  3579. 101, // Info level
  3580. ( PBYTE ) &dfsInfo101 ); // Input buffer
  3581. if ( dwStatus != ERROR_SUCCESS )
  3582. {
  3583. (g_LogEvent)(
  3584. pResourceEntry->ResourceHandle,
  3585. LOG_ERROR,
  3586. L"SmbpResetDfs: NetDfsSetInfo with computer name %1!ws! for root %2!ws!, status %3!u!...\n",
  3587. pResourceEntry->ComputerName,
  3588. pResourceEntry->Params.ShareName,
  3589. dwStatus);
  3590. }
  3591. }
  3592. return ( dwStatus );
  3593. } // SmbpResetDfs
  3594. DWORD
  3595. SmbpValidateShareName(
  3596. IN LPCWSTR lpszShareName
  3597. )
  3598. /*++
  3599. Routine Description:
  3600. Validates the name of a share.
  3601. Arguments:
  3602. lpszShareName - The name to validate.
  3603. Return Value:
  3604. ERROR_SUCCESS if successful, Win32 error code otherwise.
  3605. --*/
  3606. {
  3607. DWORD cchShareName = lstrlenW( lpszShareName );
  3608. //
  3609. // Check the length of the name, return an error if it's out of range
  3610. //
  3611. if ( ( cchShareName < 1 ) || ( cchShareName > NNLEN ) )
  3612. {
  3613. return ERROR_INVALID_PARAMETER;
  3614. }
  3615. //
  3616. // Check for illegal characters, return an error if one is found
  3617. //
  3618. if ( wcscspn( lpszShareName, ILLEGAL_NAME_CHARS_STR TEXT("*") ) < cchShareName )
  3619. {
  3620. return ERROR_INVALID_NAME;
  3621. }
  3622. //
  3623. // Return an error if the name contains only dots and spaces.
  3624. //
  3625. if ( wcsspn( lpszShareName, DOT_AND_SPACE_STR ) == cchShareName )
  3626. {
  3627. return ERROR_INVALID_NAME;
  3628. }
  3629. //
  3630. // If we get here, the name passed all of the tests, so it's valid
  3631. //
  3632. return ERROR_SUCCESS;
  3633. }// SmbpValidateShareName
  3634. DWORD
  3635. SmbpRecycleDfsService(
  3636. IN PSHARE_RESOURCE pResourceEntry
  3637. )
  3638. /*++
  3639. Routine Description:
  3640. Recycle the DFS service if necessary.
  3641. Arguments:
  3642. pResourceEntry - Supplies the pointer to the resource block
  3643. Return Value:
  3644. ERROR_SUCCESS on success, a Win32 error code otherwise.
  3645. --*/
  3646. {
  3647. DWORD dwStatus = ERROR_SUCCESS;
  3648. //
  3649. // Enter a CS to make sure multiple resources in this process do not attempt to recycle the DFS
  3650. // service at the same time. This does not cover the case where the DFS resource is hosted in a
  3651. // separate monitor but this is the best we can do at this stage.
  3652. //
  3653. EnterCriticalSection ( &SmbShareLock );
  3654. if ( g_fDfsServiceNeedsRecyling == FALSE )
  3655. {
  3656. goto FnExit;
  3657. }
  3658. (g_LogEvent)(pResourceEntry->ResourceHandle,
  3659. LOG_INFORMATION,
  3660. L"SmbpRecycleDfsService: Attempting to recycle %1!ws! service\n",
  3661. DFS_SVCNAME);
  3662. //
  3663. // If this is the first run after an upgrade/fresh install, just recycle the
  3664. // DFS service. This is necessary since the DFS service detects if clustering is
  3665. // installed only in its boot. Thus, if someone installs clustering and does not
  3666. // reboot the node or recycle the DFS service, all DFS resources will fail. Ideally,
  3667. // the DFS service should be able to detect if clustering is installed when we call
  3668. // the first DFS API, but due to risks in changing the dfssvc, we do this here.
  3669. //
  3670. dwStatus = ResUtilStopResourceService( DFS_SVCNAME );
  3671. if ( dwStatus != ERROR_SUCCESS )
  3672. {
  3673. (g_LogEvent)(pResourceEntry->ResourceHandle,
  3674. LOG_ERROR,
  3675. L"SmbpRecycleDfsService: Unable to stop %1!ws! service, status %2!u!\n",
  3676. DFS_SVCNAME,
  3677. dwStatus);
  3678. goto FnExit;
  3679. }
  3680. dwStatus = ResUtilStartResourceService( DFS_SVCNAME,
  3681. NULL );
  3682. if ( dwStatus != ERROR_SUCCESS )
  3683. {
  3684. (g_LogEvent)(pResourceEntry->ResourceHandle,
  3685. LOG_ERROR,
  3686. L"SmbpRecycleDfsService: Unable to start %1!ws! service, status %2!u!\n",
  3687. DFS_SVCNAME,
  3688. dwStatus);
  3689. goto FnExit;
  3690. }
  3691. g_fDfsServiceNeedsRecyling = FALSE;
  3692. FnExit:
  3693. LeaveCriticalSection ( &SmbShareLock );
  3694. return ( dwStatus );
  3695. }
  3696. //***********************************************************
  3697. //
  3698. // Define Function Table
  3699. //
  3700. //***********************************************************
  3701. CLRES_V1_FUNCTION_TABLE( SmbShareFunctionTable, // Name
  3702. CLRES_VERSION_V1_00, // Version
  3703. SmbShare, // Prefix
  3704. NULL, // Arbitrate
  3705. NULL, // Release
  3706. SmbShareResourceControl,// ResControl
  3707. SmbShareResourceTypeControl ); // ResTypeControl