Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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