Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2482 lines
69 KiB

  1. // smb.cpp : SMB shares, sessions and open resources
  2. #include "stdafx.h"
  3. #include "cmponent.h"
  4. #include "safetemp.h"
  5. #include "FileSvc.h"
  6. #include "DynamLnk.h" // DynamicDLL
  7. #include "smb.h"
  8. #include "ShrPgSMB.h" // Share Properties Pages
  9. #include "permpage.h" // CSecurityInformation
  10. #include "compdata.h"
  11. #include "shrpub.h"
  12. #include <activeds.h>
  13. #include <dsrole.h>
  14. #include <dsgetdc.h>
  15. #include <lmwksta.h>
  16. #include <winsock2.h>
  17. #define DONT_WANT_SHELLDEBUG
  18. #include "shlobjp.h" // LPITEMIDLIST
  19. #include "wraps.h" // Wrap_ILCreateFromPath
  20. #include "macros.h"
  21. USE_HANDLE_MACROS("FILEMGMT(smb.cpp)")
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. //
  28. // no Publish page for these system shares
  29. //
  30. LPCTSTR g_pszSystemShares[] = { _T("SYSVOL"), _T("NETLOGON"), _T("DEBUG") };
  31. class CSMBSecurityInformation : public CShareSecurityInformation
  32. {
  33. STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
  34. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  35. BOOL fDefault );
  36. STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation,
  37. PSECURITY_DESCRIPTOR pSecurityDescriptor );
  38. public:
  39. SHARE_INFO_502* m_pvolumeinfo;
  40. PSECURITY_DESCRIPTOR m_pDefaultDescriptor;
  41. CSMBSecurityInformation();
  42. ~CSMBSecurityInformation();
  43. };
  44. typedef enum _SmbApiIndex
  45. {
  46. SMB_SHARE_ENUM = 0,
  47. SMB_SESSION_ENUM,
  48. SMB_FILE_ENUM,
  49. SMB_API_BUFFER_FREE,
  50. SMB_SHARE_DEL,
  51. SMB_SESSION_DEL,
  52. SMB_FILE_CLOSE,
  53. SMB_SHARE_GET_INFO,
  54. SMB_SHARE_SET_INFO,
  55. SMB_CONNECTION_ENUM
  56. };
  57. // not subject to localization
  58. static LPCSTR g_apchFunctionNames[] = {
  59. "NetShareEnum",
  60. "NetSessionEnum",
  61. "NetFileEnum",
  62. "NetApiBufferFree",
  63. "NetShareDel",
  64. "NetSessionDel",
  65. "NetFileClose",
  66. "NetShareGetInfo",
  67. "NetShareSetInfo",
  68. "NetConnectionEnum",
  69. NULL
  70. };
  71. // not subject to localization
  72. DynamicDLL g_SmbDLL( _T("NETAPI32.DLL"), g_apchFunctionNames );
  73. typedef DWORD (*APIBUFFERFREEPROC) (LPVOID);
  74. VOID SMBFreeData(PVOID* ppv)
  75. {
  76. if (*ppv != NULL)
  77. {
  78. ASSERT( NULL != g_SmbDLL[SMB_API_BUFFER_FREE] );
  79. (void) ((APIBUFFERFREEPROC)g_SmbDLL[SMB_API_BUFFER_FREE])( *ppv );
  80. *ppv = NULL;
  81. }
  82. }
  83. SmbFileServiceProvider::SmbFileServiceProvider( CFileMgmtComponentData* pFileMgmtData )
  84. // not subject to localization
  85. : FileServiceProvider( pFileMgmtData )
  86. {
  87. VERIFY( m_strTransportSMB.LoadString( IDS_TRANSPORT_SMB ) );
  88. }
  89. /*
  90. NET_API_STATUS NET_API_FUNCTION
  91. NetShareEnum (
  92. IN LPTSTR servername,
  93. IN DWORD level,
  94. OUT LPBYTE *bufptr,
  95. IN DWORD prefmaxlen,
  96. OUT LPDWORD entriesread,
  97. OUT LPDWORD totalentries,
  98. IN OUT LPDWORD resume_handle
  99. );
  100. */
  101. typedef DWORD (*SHAREENUMPROC) (LPTSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
  102. HRESULT SmbFileServiceProvider::PopulateShares(
  103. IResultData* pResultData,
  104. CFileMgmtCookie* pcookie)
  105. {
  106. TEST_NONNULL_PTR_PARAM(pcookie);
  107. if ( !g_SmbDLL.LoadFunctionPointers() )
  108. {
  109. ASSERT(FALSE); // NETAPI32 isn't installed?
  110. return S_OK;
  111. }
  112. SHARE_INFO_2* psi2 = NULL;
  113. DWORD dwEntriesRead = 0;
  114. DWORD dwTotalEntries = 0;
  115. DWORD hEnumHandle = 0;
  116. NET_API_STATUS retval = NERR_Success;
  117. do {
  118. retval = ((SHAREENUMPROC)g_SmbDLL[SMB_SHARE_ENUM])(
  119. const_cast<LPTSTR>(pcookie->QueryTargetServer()),
  120. 2,
  121. (PBYTE*)&psi2,
  122. (DWORD)-1L,
  123. &dwEntriesRead,
  124. &dwTotalEntries,
  125. &hEnumHandle );
  126. if (NERR_Success == retval)
  127. {
  128. AddSMBShareItems( pResultData, pcookie, psi2, dwEntriesRead );
  129. psi2 = NULL;
  130. break;
  131. } else if (ERROR_MORE_DATA == retval) {
  132. ASSERT( NULL != hEnumHandle );
  133. AddSMBShareItems( pResultData, pcookie, psi2, dwEntriesRead );
  134. psi2 = NULL;
  135. continue;
  136. /*
  137. } else if (RPC_S_SERVER_UNAVAILABLE == retval && 0 == hEnumHandle) {
  138. // SMB just isn't installed, don't worry about it
  139. break;
  140. */
  141. } else {
  142. if (ERROR_ACCESS_DENIED == retval)
  143. {
  144. (void) DoErrMsgBox(
  145. GetActiveWindow(),
  146. MB_OK | MB_ICONSTOP,
  147. 0,
  148. IDS_POPUP_SMB_SHARES_NOACCESS
  149. );
  150. } else
  151. {
  152. (void) DoErrMsgBox(
  153. GetActiveWindow(),
  154. MB_OK | MB_ICONSTOP,
  155. retval,
  156. IDS_POPUP_SMB_SHARES
  157. );
  158. }
  159. break;
  160. }
  161. } while (TRUE);
  162. return HRESULT_FROM_WIN32(retval);
  163. }
  164. //
  165. // skip sharenames that contain leading/trailing spaces
  166. //
  167. BOOL IsInvalidSharename(LPCTSTR psz)
  168. {
  169. return (!psz || !*psz || _istspace(psz[0]) || _istspace(psz[lstrlen(psz) - 1]));
  170. }
  171. /*
  172. typedef struct _SHARE_INFO_2 {
  173. LPTSTR shi2_netname;
  174. DWORD shi2_type;
  175. LPTSTR shi2_remark;
  176. DWORD shi2_permissions;
  177. DWORD shi2_max_uses;
  178. DWORD shi2_current_uses;
  179. LPTSTR shi2_path;
  180. LPTSTR shi2_passwd;
  181. } SHARE_INFO_2, *PSHARE_INFO_2, *LPSHARE_INFO_2;
  182. */
  183. HRESULT SmbFileServiceProvider::AddSMBShareItems(
  184. IResultData* pResultData,
  185. CFileMgmtCookie* pParentCookie,
  186. PVOID pinfo,
  187. DWORD nItems)
  188. {
  189. TEST_NONNULL_PTR_PARAM(pParentCookie);
  190. TEST_NONNULL_PTR_PARAM(pinfo);
  191. if (0 >= nItems)
  192. return S_OK;
  193. RESULTDATAITEM tRDItem;
  194. ::ZeroMemory( &tRDItem, sizeof(tRDItem) );
  195. // CODEWORK should use MMC_ICON_CALLBACK
  196. tRDItem.nCol = COLNUM_SHARES_SHARED_FOLDER;
  197. tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  198. tRDItem.str = MMC_CALLBACK;
  199. SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pinfo;
  200. DWORD nItemsToAdd = 0;
  201. for (DWORD i = 0; i < nItems; i++ )
  202. {
  203. switch ((psi2[i]).shi2_type)
  204. {
  205. case STYPE_PRINTQ: // Do not show print shares
  206. case STYPE_DEVICE: // Do not show device shares
  207. break;
  208. default:
  209. if (!IsInvalidSharename(psi2[i].shi2_netname))
  210. nItemsToAdd++;
  211. break;
  212. }
  213. }
  214. CSmbShareCookie* pcookiearray = new CSmbShareCookie[nItemsToAdd];
  215. CSmbCookieBlock* pCookieBlock = new CSmbCookieBlock(
  216. pcookiearray,
  217. nItemsToAdd,
  218. pParentCookie->QueryNonNULLMachineName(),
  219. pinfo );
  220. pParentCookie->m_listResultCookieBlocks.AddHead( pCookieBlock );
  221. CString str;
  222. for ( ; nItems > 0; nItems--, psi2++ )
  223. {
  224. switch (psi2->shi2_type)
  225. {
  226. case STYPE_PRINTQ: // Do not show print shares
  227. case STYPE_DEVICE: // Do not show device shares
  228. continue;
  229. default:
  230. if (!IsInvalidSharename(psi2->shi2_netname))
  231. {
  232. pcookiearray->m_pobject = psi2;
  233. // WARNING cookie cast
  234. tRDItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pcookiearray);
  235. if (psi2->shi2_path &&
  236. lstrlen(psi2->shi2_path) == 3 &&
  237. *(psi2->shi2_path + 1) == _T(':') &&
  238. *(psi2->shi2_path + 2) == _T('\\') &&
  239. (*psi2->shi2_path >= _T('a') && *psi2->shi2_path <= _T('z') ||
  240. *psi2->shi2_path >= _T('A') && *psi2->shi2_path <= _T('Z')))
  241. {
  242. tRDItem.nImage = iIconSMBShare;
  243. } else
  244. {
  245. tRDItem.nImage = iIconSharesFolder;
  246. }
  247. HRESULT hr = pResultData->InsertItem(&tRDItem);
  248. ASSERT(SUCCEEDED(hr));
  249. pcookiearray++;
  250. }
  251. break;
  252. }
  253. }
  254. ASSERT( pcookiearray ==
  255. ((CSmbShareCookie*)(pCookieBlock->QueryBaseCookie(0)))+nItemsToAdd );
  256. return S_OK;
  257. }
  258. /*
  259. NET_API_STATUS NET_API_FUNCTION
  260. NetSessionEnum (
  261. IN LPTSTR servername OPTIONAL,
  262. IN LPTSTR UncClientName OPTIONAL,
  263. IN LPTSTR username OPTIONAL,
  264. IN DWORD level,
  265. OUT LPBYTE *bufptr,
  266. IN DWORD prefmaxlen,
  267. OUT LPDWORD entriesread,
  268. OUT LPDWORD totalentries,
  269. IN OUT LPDWORD resume_handle OPTIONAL
  270. );
  271. */
  272. typedef DWORD (*SESSIONENUMPROC) (LPTSTR,LPTSTR,LPTSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
  273. // if pResultData is not NULL, add sessions/resources to the listbox
  274. // if pResultData is NULL, delete all sessions/resources
  275. // if pResultData is NULL, return SUCCEEDED(hr) to continue or
  276. // FAILED(hr) to abort
  277. HRESULT SmbFileServiceProvider::EnumerateSessions(
  278. IResultData* pResultData,
  279. CFileMgmtCookie* pcookie,
  280. bool bAddToResultPane)
  281. {
  282. TEST_NONNULL_PTR_PARAM(pcookie);
  283. if ( !g_SmbDLL.LoadFunctionPointers() )
  284. return S_OK;
  285. SESSION_INFO_1* psi1 = NULL;
  286. DWORD dwEntriesRead = 0;
  287. DWORD dwTotalEntries = 0;
  288. DWORD hEnumHandle = 0;
  289. HRESULT hr = S_OK;
  290. NET_API_STATUS retval = NERR_Success;
  291. do {
  292. retval = ((SESSIONENUMPROC)g_SmbDLL[SMB_SESSION_ENUM])(
  293. const_cast<LPTSTR>(pcookie->QueryTargetServer()),
  294. NULL,
  295. NULL,
  296. 1,
  297. (PBYTE*)&psi1,
  298. (DWORD)-1L,
  299. &dwEntriesRead,
  300. &dwTotalEntries,
  301. &hEnumHandle );
  302. if (NERR_Success == retval)
  303. {
  304. hr = HandleSMBSessionItems( pResultData, pcookie, psi1, dwEntriesRead,
  305. bAddToResultPane );
  306. psi1 = NULL;
  307. break;
  308. } else if (ERROR_MORE_DATA == retval) {
  309. ASSERT( NULL != hEnumHandle );
  310. hr = HandleSMBSessionItems( pResultData, pcookie, psi1, dwEntriesRead,
  311. bAddToResultPane );
  312. psi1 = NULL;
  313. continue;
  314. } else {
  315. if (ERROR_ACCESS_DENIED == retval)
  316. {
  317. (void) DoErrMsgBox(
  318. GetActiveWindow(),
  319. MB_OK | MB_ICONSTOP,
  320. 0,
  321. IDS_POPUP_SMB_SESSIONS_NOACCESS
  322. );
  323. } else
  324. {
  325. (void) DoErrMsgBox(
  326. GetActiveWindow(),
  327. MB_OK | MB_ICONSTOP,
  328. retval,
  329. IDS_POPUP_SMB_SESSIONS
  330. );
  331. }
  332. break;
  333. }
  334. } while (S_OK == hr);
  335. return HRESULT_FROM_WIN32(retval);
  336. }
  337. /*
  338. typedef enum _COLNUM_SESSIONS {
  339. COLNUM_SESSIONS_USERNAME = 0,
  340. COLNUM_SESSIONS_COMPUTERNAME,
  341. COLNUM_SESSIONS_NUM_FILES,
  342. COLNUM_SESSIONS_CONNECTED_TIME,
  343. COLNUM_SESSIONS_IDLE_TIME,
  344. COLNUM_SESSIONS_IS_GUEST
  345. } COLNUM_SESSIONS;
  346. typedef struct _SESSION_INFO_1 {
  347. LPTSTR sesi1_cname; // client name (no backslashes)
  348. LPTSTR sesi1_username;
  349. DWORD sesi1_num_opens;
  350. DWORD sesi1_time;
  351. DWORD sesi1_idle_time;
  352. DWORD sesi1_user_flags;
  353. } SESSION_INFO_1, *PSESSION_INFO_1, *LPSESSION_INFO_1;
  354. */
  355. // if pResultData is not NULL, add sessions/resources to the listbox
  356. // if pResultData is NULL, delete all sessions/resources
  357. // if pResultData is NULL, return SUCCEEDED(hr) to continue or
  358. // FAILED(hr) to abort
  359. HRESULT SmbFileServiceProvider::HandleSMBSessionItems(
  360. IResultData* pResultData,
  361. CFileMgmtCookie* pParentCookie,
  362. PVOID pinfo,
  363. DWORD nItems,
  364. BOOL bAddToResultPane)
  365. {
  366. TEST_NONNULL_PTR_PARAM(pParentCookie);
  367. TEST_NONNULL_PTR_PARAM(pinfo);
  368. if (0 >= nItems)
  369. return S_OK;
  370. BOOL fDeleteAllItems = (NULL == pResultData);
  371. RESULTDATAITEM tRDItem;
  372. ::ZeroMemory( &tRDItem, sizeof(tRDItem) );
  373. // CODEWORK should use MMC_ICON_CALLBACK
  374. tRDItem.nImage = iIconSMBSession;
  375. tRDItem.nCol = COLNUM_SESSIONS_USERNAME;
  376. tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  377. tRDItem.str = MMC_CALLBACK;
  378. SESSION_INFO_1* psi1 = (SESSION_INFO_1*)pinfo;
  379. CSmbSessionCookie* pcookiearray = new CSmbSessionCookie[nItems];
  380. CSmbCookieBlock* pCookieBlock = new CSmbCookieBlock(
  381. pcookiearray,nItems,pParentCookie->QueryNonNULLMachineName(),pinfo );
  382. bool bAdded = false;
  383. if ( !fDeleteAllItems || !bAddToResultPane )
  384. {
  385. pParentCookie->m_listResultCookieBlocks.AddHead( pCookieBlock );
  386. bAdded = true;
  387. }
  388. for ( ; nItems > 0; nItems--, psi1++, pcookiearray++ )
  389. {
  390. pcookiearray->m_pobject = psi1;
  391. if ( bAddToResultPane )
  392. {
  393. if (fDeleteAllItems)
  394. {
  395. DWORD dwApiResult = CloseSession( pcookiearray );
  396. if (0L != dwApiResult)
  397. {
  398. CString strName;
  399. TranslateIPToComputerName(psi1->sesi1_cname, strName);
  400. (void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, dwApiResult,
  401. IDS_POPUP_SMB_DISCONNECTALLSESSION_ERROR,
  402. strName );
  403. //return S_FALSE;
  404. }
  405. continue;
  406. }
  407. // WARNING cookie cast
  408. if (psi1->sesi1_username && *(psi1->sesi1_username)) // bug#3903: exclude NULL session
  409. {
  410. tRDItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pcookiearray);
  411. HRESULT hr = pResultData->InsertItem(&tRDItem);
  412. ASSERT(SUCCEEDED(hr));
  413. }
  414. }
  415. }
  416. if ( !bAdded ) // they were not added to the parent cookie's list
  417. delete pCookieBlock;
  418. return S_OK;
  419. }
  420. /*
  421. NET_API_STATUS NET_API_FUNCTION
  422. NetFileEnum (
  423. IN LPTSTR servername OPTIONAL,
  424. IN LPTSTR basepath OPTIONAL,
  425. IN LPTSTR username OPTIONAL,
  426. IN DWORD level,
  427. OUT LPBYTE *bufptr,
  428. IN DWORD prefmaxlen,
  429. OUT LPDWORD entriesread,
  430. OUT LPDWORD totalentries,
  431. IN OUT LPDWORD resume_handle OPTIONAL
  432. );
  433. */
  434. typedef DWORD (*FILEENUMPROC) (LPTSTR,LPTSTR,LPTSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
  435. // if pResultData is not NULL, add sessions/resources to the listbox
  436. // if pResultData is NULL, delete all sessions/resources
  437. // if pResultData is NULL, return SUCCEEDED(hr) to continue or
  438. // FAILED(hr) to abort
  439. HRESULT SmbFileServiceProvider::EnumerateResources(
  440. IResultData* pResultData,
  441. CFileMgmtCookie* pcookie)
  442. {
  443. TEST_NONNULL_PTR_PARAM(pcookie);
  444. if ( !g_SmbDLL.LoadFunctionPointers() )
  445. return S_OK;
  446. FILE_INFO_3* pfi3 = NULL;
  447. DWORD dwEntriesRead = 0;
  448. DWORD dwTotalEntries = 0;
  449. DWORD hEnumHandle = 0;
  450. HRESULT hr = S_OK;
  451. NET_API_STATUS retval = NERR_Success;
  452. do {
  453. retval = ((FILEENUMPROC)g_SmbDLL[SMB_FILE_ENUM])(
  454. const_cast<LPTSTR>(pcookie->QueryTargetServer()),
  455. NULL,
  456. NULL,
  457. 3,
  458. (PBYTE*)&pfi3,
  459. (DWORD)-1L,
  460. &dwEntriesRead,
  461. &dwTotalEntries,
  462. &hEnumHandle );
  463. if (NERR_Success == retval)
  464. {
  465. hr = HandleSMBResourceItems( pResultData, pcookie, pfi3, dwEntriesRead );
  466. pfi3 = NULL;
  467. break;
  468. } else if (ERROR_MORE_DATA == retval) {
  469. ASSERT( NULL != hEnumHandle );
  470. hr = HandleSMBResourceItems( pResultData, pcookie, pfi3, dwEntriesRead );
  471. pfi3 = NULL;
  472. continue;
  473. } else {
  474. if (ERROR_ACCESS_DENIED == retval)
  475. {
  476. (void) DoErrMsgBox(
  477. GetActiveWindow(),
  478. MB_OK | MB_ICONSTOP,
  479. 0,
  480. IDS_POPUP_SMB_RESOURCES_NOACCESS
  481. );
  482. } else
  483. {
  484. (void) DoErrMsgBox(
  485. GetActiveWindow(),
  486. MB_OK | MB_ICONSTOP,
  487. retval,
  488. IDS_POPUP_SMB_RESOURCES
  489. );
  490. }
  491. break;
  492. }
  493. } while (S_OK == hr);
  494. return HRESULT_FROM_WIN32(retval);
  495. }
  496. /*
  497. typedef enum _COLNUM_RESOURCES {
  498. COLNUM_RESOURCES_FILENAME = 0,
  499. COLNUM_RESOURCES_USERNAME,
  500. COLNUM_RESOURCES_NUM_LOCKS, // we don't try to display sharename for now, since
  501. // only SMB has this information
  502. COLNUM_RESOURCES_OPEN_MODE
  503. } COLNUM_RESOURCES;
  504. typedef struct _FILE_INFO_3 {
  505. DWORD fi3_id;
  506. DWORD fi3_permissions;
  507. DWORD fi3_num_locks;
  508. LPTSTR fi3_pathname;
  509. LPTSTR fi3_username;
  510. } FILE_INFO_3, *PFILE_INFO_3, *LPFILE_INFO_3;
  511. */
  512. // if pResultData is not NULL, add sessions/resources to the listbox
  513. // if pResultData is NULL, delete all sessions/resources
  514. // if pResultData is NULL, return SUCCEEDED(hr) to continue or
  515. // FAILED(hr) to abort
  516. HRESULT SmbFileServiceProvider::HandleSMBResourceItems(
  517. IResultData* pResultData,
  518. CFileMgmtCookie* pParentCookie,
  519. PVOID pinfo,
  520. DWORD nItems)
  521. {
  522. TEST_NONNULL_PTR_PARAM(pParentCookie);
  523. TEST_NONNULL_PTR_PARAM(pinfo);
  524. if (0 >= nItems)
  525. return S_OK;
  526. BOOL fDeleteAllItems = (NULL == pResultData);
  527. RESULTDATAITEM tRDItem;
  528. ::ZeroMemory( &tRDItem, sizeof(tRDItem) );
  529. // CODEWORK should use MMC_ICON_CALLBACK
  530. tRDItem.nImage = iIconSMBResource;
  531. tRDItem.nCol = COLNUM_RESOURCES_FILENAME;
  532. tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  533. tRDItem.str = MMC_CALLBACK;
  534. FILE_INFO_3* pfi3 = (FILE_INFO_3*)pinfo;
  535. CSmbResourceCookie* pcookiearray = new CSmbResourceCookie[nItems];
  536. CSmbCookieBlock* pCookieBlock = new CSmbCookieBlock(
  537. pcookiearray,nItems,pParentCookie->QueryNonNULLMachineName(),pinfo );
  538. if (!fDeleteAllItems)
  539. {
  540. pParentCookie->m_listResultCookieBlocks.AddHead( pCookieBlock );
  541. }
  542. CString str;
  543. for ( ; nItems > 0; nItems--, pfi3++, pcookiearray++ )
  544. {
  545. pcookiearray->m_pobject = pfi3;
  546. if (fDeleteAllItems)
  547. {
  548. DWORD dwApiResult = CloseResource( pcookiearray );
  549. if (0L != dwApiResult)
  550. {
  551. (void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, dwApiResult,
  552. IDS_POPUP_SMB_DISCONNECTALLRESOURCE_ERROR,
  553. pfi3->fi3_pathname );
  554. return S_FALSE;
  555. }
  556. continue;
  557. }
  558. // WARNING cookie cast
  559. tRDItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pcookiearray);
  560. HRESULT hr = pResultData->InsertItem(&tRDItem);
  561. ASSERT(SUCCEEDED(hr));
  562. }
  563. if (fDeleteAllItems) // they were not added to the parent cookie's list
  564. delete pCookieBlock;
  565. return S_OK;
  566. }
  567. /*
  568. NET_API_STATUS NET_API_FUNCTION
  569. NetShareDel (
  570. IN LPTSTR servername,
  571. IN LPTSTR netname,
  572. IN DWORD reserved
  573. );
  574. */
  575. typedef DWORD (*SHAREGETINFOPROC) (LPTSTR,LPTSTR,DWORD,LPBYTE*);
  576. typedef DWORD (*SHAREDELPROC) (LPTSTR,LPTSTR,DWORD);
  577. DWORD SmbFileServiceProvider::OpenShare( LPCTSTR lpcszServerName, LPCTSTR lpcszShareName )
  578. {
  579. if ( !g_SmbDLL.LoadFunctionPointers() )
  580. return NERR_Success;
  581. BOOL bLocal = IsLocalComputername(lpcszServerName);
  582. PTSTR pszPath = NULL;
  583. SHARE_INFO_2 *pshi2 = NULL;
  584. if (bLocal)
  585. {
  586. NET_API_STATUS dwRet = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
  587. const_cast<LPTSTR>(lpcszServerName),
  588. const_cast<LPTSTR>(lpcszShareName),
  589. 2,
  590. (LPBYTE*)&pshi2);
  591. if (NERR_Success != dwRet)
  592. return dwRet;
  593. pszPath = pshi2->shi2_path;
  594. } else
  595. {
  596. pszPath = (PTSTR)calloc(lstrlen(lpcszServerName) + lstrlen(lpcszShareName) + 4, sizeof(TCHAR));
  597. if (pszPath)
  598. {
  599. TCHAR *p = pszPath;
  600. if (_T('\\') != *lpcszServerName)
  601. {
  602. *p++ = _T('\\');
  603. *p++ = _T('\\');
  604. }
  605. lstrcpy(p, lpcszServerName);
  606. p += lstrlen(lpcszServerName);
  607. *p++ = _T('\\');
  608. lstrcpy(p, lpcszShareName);
  609. }
  610. }
  611. if (!pszPath || !*pszPath)
  612. {
  613. (void) DoErrMsgBox(GetActiveWindow(), MB_OK, 0, IDS_CANNOT_OPENSHARE, lpcszShareName);
  614. } else if (32 >= (INT_PTR) ShellExecute(
  615. NULL, // Handle to window
  616. _T("explore"), // Action to take
  617. pszPath, // Folder to explore
  618. NULL, // Parameters
  619. NULL, // Default directory
  620. SW_SHOWNORMAL // Show command
  621. ))
  622. {
  623. (void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, 0, IDS_MSG_EXPLORE_FAILURE, pszPath);
  624. }
  625. if (!bLocal && pszPath)
  626. free(pszPath);
  627. if (pshi2)
  628. FreeData(pshi2);
  629. return NERR_Success;
  630. }
  631. /*
  632. NET_API_STATUS NET_API_FUNCTION
  633. NetConnectionEnum (
  634. IN LMSTR servername OPTIONAL,
  635. IN LMSTR qualifier,
  636. IN DWORD level,
  637. OUT LPBYTE *bufptr,
  638. IN DWORD prefmaxlen,
  639. OUT LPDWORD entriesread,
  640. OUT LPDWORD totalentries,
  641. IN OUT LPDWORD resume_handle OPTIONAL
  642. );
  643. */
  644. typedef DWORD (*CONNECTIONENUMPROC) (LPTSTR,LPTSTR,DWORD,LPBYTE *,DWORD,LPDWORD,LPDWORD,LPDWORD);
  645. // S_OK: user wants to continue
  646. // S_FALSE: user wants to cancel the operation and keep the share
  647. // E_FAIL: share doesn't exist, needs to refresh
  648. HRESULT SmbFileServiceProvider::ConfirmDeleteShare( LPCTSTR lpcszServerName, LPCTSTR lpcszShareName )
  649. {
  650. if ( !g_SmbDLL.LoadFunctionPointers() )
  651. return E_FAIL;
  652. CONNECTION_INFO_1* pBuf = NULL;
  653. DWORD dwEntry = 0;
  654. DWORD dwTotal = 0;
  655. NET_API_STATUS dwRet = ((CONNECTIONENUMPROC)g_SmbDLL[SMB_CONNECTION_ENUM])(
  656. const_cast<LPTSTR>(lpcszServerName),
  657. const_cast<LPTSTR>(lpcszShareName),
  658. 1,
  659. (LPBYTE*)&pBuf,
  660. (DWORD)-1,
  661. &dwEntry,
  662. &dwTotal,
  663. NULL);
  664. if (NERR_NetNameNotFound == dwRet)
  665. return E_FAIL;
  666. if (NERR_Success != dwRet && ERROR_MORE_DATA != dwRet)
  667. return E_FAIL;
  668. UINT cConns = dwTotal;
  669. UINT cOpens = 0;
  670. for (DWORD i = 0; i < dwEntry; i++)
  671. {
  672. cOpens += pBuf[i].coni1_num_opens;
  673. }
  674. NetApiBufferFree(pBuf);
  675. if (cConns > 0)
  676. {
  677. if (cOpens > 0)
  678. {
  679. if (IDYES != DoErrMsgBox(
  680. GetActiveWindow(),
  681. MB_YESNO,
  682. 0,
  683. IDS_s_CONFIRM_DELETESHARE_FILE,
  684. cOpens,
  685. cConns,
  686. lpcszShareName))
  687. {
  688. return S_FALSE;
  689. }
  690. } else // (cConns > 0)
  691. {
  692. if (IDYES != DoErrMsgBox(
  693. GetActiveWindow(),
  694. MB_YESNO,
  695. 0,
  696. IDS_s_CONFIRM_DELETESHARE_CONN,
  697. cConns,
  698. lpcszShareName))
  699. {
  700. return S_FALSE;
  701. }
  702. }
  703. } else
  704. {
  705. if (IDYES != DoErrMsgBox(
  706. GetActiveWindow(),
  707. MB_YESNO,
  708. 0,
  709. IDS_s_CONFIRM_DELETESHARE,
  710. lpcszShareName))
  711. {
  712. return S_FALSE;
  713. }
  714. }
  715. return S_OK;
  716. }
  717. DWORD SmbFileServiceProvider::DeleteShare( LPCTSTR lpcszServerName, LPCTSTR lpcszShareName )
  718. {
  719. if ( !g_SmbDLL.LoadFunctionPointers() )
  720. return S_OK;
  721. SHARE_INFO_2 *pshi2 = NULL;
  722. NET_API_STATUS dwRet = NERR_Success;
  723. BOOL bLocal = TRUE;
  724. bLocal = IsLocalComputername(lpcszServerName);
  725. if (bLocal)
  726. {
  727. dwRet = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
  728. const_cast<LPTSTR>(lpcszServerName),
  729. const_cast<LPTSTR>(lpcszShareName),
  730. 2,
  731. (LPBYTE*)&pshi2);
  732. if (NERR_NetNameNotFound == dwRet)
  733. return NERR_Success;
  734. if (NERR_Success != dwRet)
  735. return dwRet;
  736. }
  737. dwRet = ((SHAREDELPROC)g_SmbDLL[SMB_SHARE_DEL])(
  738. const_cast<LPTSTR>(lpcszServerName),
  739. const_cast<LPTSTR>(lpcszShareName),
  740. 0L );
  741. if (NERR_NetNameNotFound == dwRet)
  742. dwRet = NERR_Success;
  743. if (NERR_Success == dwRet)
  744. {
  745. IADsContainer *piADsContainer = m_pFileMgmtData->GetIADsContainer(); // no need to AddRef
  746. if (piADsContainer)
  747. {
  748. CString strCNName = _T("CN=");
  749. strCNName += lpcszShareName;
  750. (void)piADsContainer->Delete(_T("volume"), (LPTSTR)(LPCTSTR)strCNName);
  751. }
  752. }
  753. if (bLocal)
  754. {
  755. if (dwRet == NERR_Success)
  756. {
  757. SHChangeNotify(
  758. SHCNE_NETUNSHARE,
  759. SHCNF_PATH | SHCNF_FLUSHNOWAIT ,
  760. pshi2->shi2_path,
  761. 0);
  762. }
  763. FreeData( pshi2 );
  764. }
  765. return dwRet;
  766. }
  767. /*
  768. NET_API_STATUS NET_API_FUNCTION
  769. NetSessionDel (
  770. IN LPTSTR servername OPTIONAL,
  771. IN LPTSTR UncClientName,
  772. IN LPTSTR username
  773. );
  774. */
  775. typedef DWORD (*SESSIONDELPROC) (LPTSTR,LPTSTR,LPTSTR);
  776. BOOL BlockRemoteAdminSession(
  777. IN PCTSTR i_pszTargetServer,
  778. IN PCTSTR i_pszClientName,
  779. IN PCTSTR i_pszUserName,
  780. IN DWORD i_dwNumOpenSessions
  781. );
  782. BOOL BlockRemoteAdminFile(
  783. IN PCTSTR i_pszTargetServer,
  784. IN PCTSTR i_pszPathName,
  785. IN PCTSTR i_pszUserName
  786. );
  787. DWORD SmbFileServiceProvider::CloseSession(CFileMgmtResultCookie* pcookie)
  788. {
  789. if ( !g_SmbDLL.LoadFunctionPointers() )
  790. return S_OK;
  791. ASSERT( FILEMGMT_SESSION == pcookie->QueryObjectType() );
  792. SESSION_INFO_1* psi1 = (SESSION_INFO_1*)pcookie->m_pobject;
  793. ASSERT( NULL != psi1 &&
  794. NULL != psi1->sesi1_cname &&
  795. TEXT('\0') != *(psi1->sesi1_cname) );
  796. PCTSTR pszTargetServer = pcookie->QueryTargetServer();
  797. if (BlockRemoteAdminSession(pszTargetServer, psi1->sesi1_cname, psi1->sesi1_username, psi1->sesi1_num_opens))
  798. return NERR_Success;
  799. CString strCName = _T("\\\\");
  800. strCName += psi1->sesi1_cname;
  801. DWORD dwRetval = ((SESSIONDELPROC)g_SmbDLL[SMB_SESSION_DEL])(
  802. const_cast<LPTSTR>(pszTargetServer),
  803. const_cast<LPTSTR>((LPCTSTR)strCName),
  804. psi1->sesi1_username );
  805. return (NERR_NoSuchSession == dwRetval) ? NERR_Success : dwRetval;
  806. }
  807. /*
  808. NET_API_STATUS NET_API_FUNCTION
  809. NetFileClose (
  810. IN LPTSTR servername OPTIONAL,
  811. IN DWORD fileid
  812. );
  813. */
  814. typedef DWORD (*FILECLOSEPROC) (LPTSTR,DWORD);
  815. DWORD SmbFileServiceProvider::CloseResource(CFileMgmtResultCookie* pcookie)
  816. {
  817. if ( !g_SmbDLL.LoadFunctionPointers() )
  818. return S_OK;
  819. ASSERT( FILEMGMT_RESOURCE == pcookie->QueryObjectType() );
  820. FILE_INFO_3* pfileinfo = (FILE_INFO_3*)pcookie->m_pobject;
  821. ASSERT( NULL != pfileinfo );
  822. PCTSTR pszTargetServer = pcookie->QueryTargetServer();
  823. if (BlockRemoteAdminFile(pszTargetServer, pfileinfo->fi3_pathname, pfileinfo->fi3_username))
  824. return NERR_Success;
  825. DWORD dwRetval = ((FILECLOSEPROC)g_SmbDLL[SMB_FILE_CLOSE])(
  826. const_cast<LPTSTR>(pszTargetServer),
  827. pfileinfo->fi3_id );
  828. return (NERR_FileIdNotFound == dwRetval) ? NERR_Success : dwRetval;
  829. }
  830. /*
  831. NET_API_STATUS NET_API_FUNCTION
  832. NetShareGetInfo (
  833. IN LPTSTR servername,
  834. IN LPTSTR netname,
  835. IN DWORD level,
  836. OUT LPBYTE *bufptr
  837. );
  838. NET_API_STATUS NET_API_FUNCTION
  839. NetShareSetInfo (
  840. IN LPTSTR servername,
  841. IN LPTSTR netname,
  842. IN DWORD level,
  843. IN LPBYTE buf,
  844. OUT LPDWORD parm_err
  845. );
  846. typedef struct _SHARE_INFO_2 {
  847. LPTSTR shi2_netname;
  848. DWORD shi2_type;
  849. LPTSTR shi2_remark;
  850. DWORD shi2_permissions;
  851. DWORD shi2_max_uses;
  852. DWORD shi2_current_uses;
  853. LPTSTR shi2_path;
  854. LPTSTR shi2_passwd;
  855. } SHARE_INFO_2, *PSHARE_INFO_2, *LPSHARE_INFO_2;
  856. */
  857. typedef DWORD (*SHARESETINFOPROC) (LPTSTR,LPTSTR,DWORD,LPBYTE,LPDWORD);
  858. VOID SmbFileServiceProvider::DisplayShareProperties(
  859. LPPROPERTYSHEETCALLBACK pCallBack,
  860. LPDATAOBJECT pDataObject,
  861. LONG_PTR handle)
  862. {
  863. HRESULT hr = S_OK;
  864. CSharePageGeneralSMB * pPage = new CSharePageGeneralSMB();
  865. if ( !pPage->Load( m_pFileMgmtData, pDataObject ) )
  866. return;
  867. //
  868. // enforce the following calling order to work around MMC bug#464475:
  869. // m_psp.pfnCallback ==> my PropSheetPageProc ==> MMC callback ==> MFC callback
  870. //
  871. MMCPropPageCallback(INOUT &pPage->m_psp);
  872. // This mechanism deletes the CFileMgmtGeneral when the property sheet is finished
  873. pPage->m_pfnOriginalPropSheetPageProc = pPage->m_psp.pfnCallback;
  874. pPage->m_psp.lParam = reinterpret_cast<LPARAM>(pPage);
  875. pPage->m_psp.pfnCallback = &CSharePageGeneralSMB::PropSheetPageProc;
  876. pPage->m_handle = handle;
  877. HPROPSHEETPAGE hPage=MyCreatePropertySheetPage(&pPage->m_psp);
  878. pCallBack->AddPage(hPage);
  879. if (pPage->m_dwShareType & (STYPE_IPC | STYPE_SPECIAL))
  880. {
  881. (void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONINFORMATION, 0, IDS_s_POPUP_ADMIN_SHARE);
  882. return;
  883. }
  884. //
  885. // display the "Publish" page
  886. //
  887. if (m_pFileMgmtData->GetSchemaSupportSharePublishing() && CheckPolicyOnSharePublish(pPage->m_strShareName))
  888. {
  889. CSharePagePublish * pPagePublish = new CSharePagePublish();
  890. if ( !pPagePublish->Load( m_pFileMgmtData, pDataObject ) )
  891. return;
  892. //
  893. // enforce the following calling order to work around MMC bug#464475:
  894. // m_psp.pfnCallback ==> my PropSheetPageProc ==> MMC callback ==> MFC callback
  895. //
  896. MMCPropPageCallback(INOUT &pPagePublish->m_psp);
  897. // This mechanism deletes the pPagePublish when the property sheet is finished
  898. pPagePublish->m_pfnOriginalPropSheetPageProc = pPagePublish->m_psp.pfnCallback;
  899. pPagePublish->m_psp.lParam = reinterpret_cast<LPARAM>(pPagePublish);
  900. pPagePublish->m_psp.pfnCallback = &CSharePagePublish::PropSheetPageProc;
  901. pPagePublish->m_handle = handle;
  902. HPROPSHEETPAGE hPagePublish=MyCreatePropertySheetPage(&pPagePublish->m_psp);
  903. pCallBack->AddPage(hPagePublish);
  904. }
  905. //
  906. // display the "Share Security" page
  907. //
  908. CComObject<CSMBSecurityInformation>* psecinfo = NULL;
  909. hr = CComObject<CSMBSecurityInformation>::CreateInstance(&psecinfo);
  910. if ( SUCCEEDED(hr) )
  911. MyCreateShareSecurityPage(
  912. pCallBack,
  913. psecinfo,
  914. pPage->m_strMachineName,
  915. pPage->m_strShareName );
  916. CreateFolderSecurityPropPage(pCallBack, pDataObject);
  917. }
  918. DWORD SmbFileServiceProvider::ReadShareType(
  919. LPCTSTR ptchServerName,
  920. LPCTSTR ptchShareName,
  921. OUT DWORD* pdwShareType)
  922. {
  923. if ( !g_SmbDLL.LoadFunctionPointers() )
  924. {
  925. ASSERT(FALSE);
  926. return S_OK;
  927. }
  928. *pdwShareType = 0;
  929. SHARE_INFO_2* psi2 = NULL;
  930. NET_API_STATUS retval = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
  931. const_cast<LPTSTR>(ptchServerName),
  932. const_cast<LPTSTR>(ptchShareName),
  933. 2,
  934. (LPBYTE*)&psi2);
  935. if (NERR_Success != retval)
  936. return retval;
  937. ASSERT( NULL != psi2 );
  938. *pdwShareType = psi2->shi2_type;
  939. FreeData(psi2);
  940. return NERR_Success;
  941. }
  942. DWORD SmbFileServiceProvider::ReadShareProperties(
  943. LPCTSTR ptchServerName,
  944. LPCTSTR ptchShareName,
  945. OUT PVOID* ppvPropertyBlock,
  946. OUT CString& strDescription,
  947. OUT CString& strPath,
  948. OUT BOOL* pfEditDescription,
  949. OUT BOOL* pfEditPath,
  950. OUT DWORD* pdwShareType)
  951. {
  952. if ( !g_SmbDLL.LoadFunctionPointers() )
  953. {
  954. ASSERT(FALSE);
  955. return S_OK;
  956. }
  957. if (ppvPropertyBlock) *ppvPropertyBlock = NULL;
  958. if (pdwShareType) *pdwShareType = 0;
  959. if (pfEditDescription) *pfEditDescription = TRUE;
  960. if (pfEditPath) *pfEditPath = FALSE;
  961. SHARE_INFO_2* psi2 = NULL;
  962. NET_API_STATUS retval = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
  963. const_cast<LPTSTR>(ptchServerName),
  964. const_cast<LPTSTR>(ptchShareName),
  965. 2,
  966. (LPBYTE*)&psi2);
  967. if (NERR_Success != retval)
  968. return retval;
  969. strDescription = psi2->shi2_remark;
  970. strPath = psi2->shi2_path;
  971. if (pdwShareType)
  972. *pdwShareType = psi2->shi2_type;
  973. if (ppvPropertyBlock)
  974. {
  975. *ppvPropertyBlock = psi2; // will be freed by the caller
  976. } else
  977. {
  978. FreeData((LPVOID)psi2);
  979. }
  980. return NERR_Success;
  981. }
  982. DWORD SmbFileServiceProvider::WriteShareProperties(
  983. OUT LPCTSTR ptchServerName,
  984. OUT LPCTSTR ptchShareName,
  985. OUT PVOID pvPropertyBlock,
  986. OUT LPCTSTR ptchDescription,
  987. OUT LPCTSTR ptchPath)
  988. {
  989. ASSERT( NULL != pvPropertyBlock );
  990. if ( !g_SmbDLL.LoadFunctionPointers() )
  991. return S_OK;
  992. SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pvPropertyBlock;
  993. //
  994. // CODEWORK Note that this leaves psi2 invalid after the call, but that any subsequent
  995. // use will replace these pointers.
  996. //
  997. psi2->shi2_remark = const_cast<LPTSTR>(ptchDescription);
  998. psi2->shi2_path = const_cast<LPTSTR>(ptchPath);
  999. DWORD dwDummy;
  1000. DWORD retval = ((SHARESETINFOPROC)g_SmbDLL[SMB_SHARE_SET_INFO])(
  1001. const_cast<LPTSTR>(ptchServerName),
  1002. const_cast<LPTSTR>(ptchShareName),
  1003. 2,
  1004. (LPBYTE)psi2,
  1005. &dwDummy);
  1006. psi2->shi2_remark = NULL;
  1007. psi2->shi2_path = NULL;
  1008. return retval;
  1009. }
  1010. HRESULT TranslateManagedBy(
  1011. IN PCTSTR i_pszDCName,
  1012. IN PCTSTR i_pszIn,
  1013. OUT CString& o_strOut,
  1014. IN ADS_NAME_TYPE_ENUM i_formatIn,
  1015. IN ADS_NAME_TYPE_ENUM i_formatOut
  1016. )
  1017. {
  1018. o_strOut.Empty();
  1019. HRESULT hr = S_OK;
  1020. if (!i_pszIn || !*i_pszIn)
  1021. return hr;
  1022. CComPtr<IADsNameTranslate> spiADsNameTranslate;
  1023. hr = CoCreateInstance(CLSID_NameTranslate, NULL, CLSCTX_INPROC_SERVER, IID_IADsNameTranslate, (void **)&spiADsNameTranslate);
  1024. if (FAILED(hr)) return hr;
  1025. hr = spiADsNameTranslate->Init(ADS_NAME_INITTYPE_SERVER, (LPTSTR)i_pszDCName);
  1026. if (FAILED(hr)) return hr;
  1027. hr = spiADsNameTranslate->Set(i_formatIn, (LPTSTR)i_pszIn);
  1028. if (FAILED(hr)) return hr;
  1029. CComBSTR sbstr;
  1030. hr = spiADsNameTranslate->Get(i_formatOut, &sbstr);
  1031. if (SUCCEEDED(hr))
  1032. o_strOut = (BSTR)sbstr;
  1033. return hr;
  1034. }
  1035. HRESULT SmbFileServiceProvider::ReadSharePublishInfo(
  1036. LPCTSTR ptchServerName,
  1037. LPCTSTR ptchShareName,
  1038. OUT BOOL* pbPublish,
  1039. OUT CString& strUNCPath,
  1040. OUT CString& strDescription,
  1041. OUT CString& strKeywords,
  1042. OUT CString& strManagedBy)
  1043. {
  1044. HRESULT hr = S_OK;
  1045. do {
  1046. CString strADsPath, strDCName;
  1047. hr = GetADsPathOfComputerObject(ptchServerName, strADsPath, strDCName);
  1048. if (S_OK != hr) break;
  1049. CComPtr<IADsContainer> spiADsContainer;
  1050. hr = ADsGetObject(strADsPath, IID_IADsContainer, (void**)&spiADsContainer);
  1051. if (FAILED(hr)) break;
  1052. CString strCNName = _T("CN=");
  1053. strCNName += ptchShareName;
  1054. CComPtr<IDispatch> spiDispatch;
  1055. hr = spiADsContainer->GetObject(_T("volume"), (LPTSTR)(LPCTSTR)strCNName, &spiDispatch);
  1056. if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hr)
  1057. {
  1058. hr = S_OK;
  1059. *pbPublish = FALSE;
  1060. break;
  1061. }
  1062. if (FAILED(hr)) break;
  1063. *pbPublish = TRUE;
  1064. CComPtr<IADs> spiADs;
  1065. hr = spiDispatch->QueryInterface(IID_IADs, (void**)&spiADs);
  1066. if (FAILED(hr)) break;
  1067. VARIANT var;
  1068. VariantInit(&var);
  1069. hr = spiADs->Get(_T("uNCName"), &var);
  1070. if (FAILED(hr)) break;
  1071. strUNCPath = V_BSTR(&var);
  1072. VariantClear(&var);
  1073. hr = spiADs->Get(_T("description"), &var);
  1074. if (SUCCEEDED(hr))
  1075. {
  1076. hr = GetSingleOrMultiValuesFromVarArray(&var, strDescription);
  1077. VariantClear(&var);
  1078. } else if (E_ADS_PROPERTY_NOT_FOUND == hr)
  1079. hr = S_OK;
  1080. else
  1081. break;
  1082. hr = spiADs->Get(_T("keywords"), &var);
  1083. if (SUCCEEDED(hr))
  1084. {
  1085. hr = GetSingleOrMultiValuesFromVarArray(&var, strKeywords);
  1086. VariantClear(&var);
  1087. } else if (E_ADS_PROPERTY_NOT_FOUND == hr)
  1088. hr = S_OK;
  1089. else
  1090. break;
  1091. hr = spiADs->Get(_T("managedBy"), &var);
  1092. if (SUCCEEDED(hr))
  1093. {
  1094. // 1st, try map to a UPN [email protected]
  1095. hr = TranslateManagedBy(strDCName,
  1096. V_BSTR(&var),
  1097. strManagedBy,
  1098. ADS_NAME_TYPE_1779,
  1099. ADS_NAME_TYPE_USER_PRINCIPAL_NAME);
  1100. // in case no UPN, map to NT4 style domain\user
  1101. if (FAILED(hr))
  1102. hr = TranslateManagedBy(strDCName,
  1103. V_BSTR(&var),
  1104. strManagedBy,
  1105. ADS_NAME_TYPE_1779,
  1106. ADS_NAME_TYPE_NT4);
  1107. VariantClear(&var);
  1108. } else if (E_ADS_PROPERTY_NOT_FOUND == hr)
  1109. hr = S_OK;
  1110. else
  1111. break;
  1112. } while (0);
  1113. return hr;
  1114. }
  1115. HRESULT SmbFileServiceProvider::WriteSharePublishInfo(
  1116. LPCTSTR ptchServerName,
  1117. LPCTSTR ptchShareName,
  1118. IN BOOL bPublish,
  1119. LPCTSTR ptchDescription,
  1120. LPCTSTR ptchKeywords,
  1121. LPCTSTR ptchManagedBy)
  1122. {
  1123. HRESULT hr = S_OK;
  1124. do {
  1125. CString strADsPath, strDCName;
  1126. hr = GetADsPathOfComputerObject(ptchServerName, strADsPath, strDCName);
  1127. if (S_OK != hr) break;
  1128. CComPtr<IADsContainer> spiADsContainer;
  1129. hr = ADsGetObject(strADsPath, IID_IADsContainer, (void**)&spiADsContainer);
  1130. if (FAILED(hr)) break;
  1131. CString strCNName = _T("CN=");
  1132. strCNName += ptchShareName;
  1133. if (!bPublish)
  1134. {
  1135. hr = spiADsContainer->Delete(_T("volume"), (LPTSTR)(LPCTSTR)strCNName);
  1136. if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hr)
  1137. hr = S_OK;
  1138. break;
  1139. }
  1140. BOOL bNewObject = FALSE;
  1141. CComPtr<IDispatch> spiDispatch;
  1142. hr = spiADsContainer->GetObject(_T("volume"), (LPTSTR)(LPCTSTR)strCNName, &spiDispatch);
  1143. if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hr)
  1144. {
  1145. hr = spiADsContainer->Create(_T("volume"), (LPTSTR)(LPCTSTR)strCNName, &spiDispatch);
  1146. bNewObject = TRUE;
  1147. }
  1148. if (FAILED(hr)) break;
  1149. CComPtr<IADs> spiADs;
  1150. hr = spiDispatch->QueryInterface(IID_IADs, (void**)&spiADs);
  1151. if (FAILED(hr)) break;
  1152. VARIANT var;
  1153. VariantInit(&var);
  1154. if (bNewObject)
  1155. {
  1156. CString strUNCName;
  1157. if (!_tcsncmp(ptchServerName, _T("\\\\"), 2))
  1158. {
  1159. strUNCName = ptchServerName;
  1160. } else
  1161. {
  1162. strUNCName = _T("\\\\");
  1163. strUNCName += ptchServerName;
  1164. }
  1165. strUNCName += _T("\\");
  1166. strUNCName += ptchShareName;
  1167. V_BSTR(&var) = SysAllocString(strUNCName);
  1168. V_VT(&var) = VT_BSTR;
  1169. hr = spiADs->Put(_T("uNCName"), var);
  1170. VariantClear(&var);
  1171. if (FAILED(hr)) break;
  1172. }
  1173. // according to schema, description is multi valued.
  1174. // but we're treating it as single value
  1175. if (ptchDescription && *ptchDescription)
  1176. {
  1177. V_BSTR(&var) = SysAllocString(ptchDescription);
  1178. V_VT(&var) = VT_BSTR;
  1179. hr = spiADs->Put(_T("description"), var);
  1180. VariantClear(&var);
  1181. } else if (!bNewObject)
  1182. {
  1183. V_VT(&var)=VT_NULL;
  1184. hr = spiADs->PutEx(ADS_PROPERTY_CLEAR, _T("description"), var);
  1185. VariantClear(&var);
  1186. }
  1187. if (FAILED(hr)) break;
  1188. if (ptchKeywords && *ptchKeywords)
  1189. {
  1190. hr = PutMultiValuesIntoVarArray(ptchKeywords, &var);
  1191. if (SUCCEEDED(hr))
  1192. {
  1193. hr = spiADs->Put(_T("keywords"), var);
  1194. VariantClear(&var);
  1195. }
  1196. } else if (!bNewObject)
  1197. {
  1198. V_VT(&var)=VT_NULL;
  1199. hr = spiADs->PutEx(ADS_PROPERTY_CLEAR, _T("keywords"), var);
  1200. VariantClear(&var);
  1201. }
  1202. if (FAILED(hr)) break;
  1203. if (ptchManagedBy && *ptchManagedBy)
  1204. {
  1205. CString strManagedByFQDN;
  1206. hr = TranslateManagedBy(strDCName,
  1207. ptchManagedBy,
  1208. strManagedByFQDN,
  1209. (_tcschr(ptchManagedBy, _T('@')) ? ADS_NAME_TYPE_USER_PRINCIPAL_NAME : ADS_NAME_TYPE_NT4),
  1210. ADS_NAME_TYPE_1779);
  1211. if (SUCCEEDED(hr))
  1212. {
  1213. V_BSTR(&var) = SysAllocString(strManagedByFQDN);
  1214. V_VT(&var) = VT_BSTR;
  1215. hr = spiADs->Put(_T("managedBy"), var);
  1216. VariantClear(&var);
  1217. }
  1218. } else if (!bNewObject)
  1219. {
  1220. V_VT(&var)=VT_NULL;
  1221. hr = spiADs->PutEx(ADS_PROPERTY_CLEAR, _T("managedBy"), var);
  1222. VariantClear(&var);
  1223. }
  1224. if (FAILED(hr)) break;
  1225. hr = spiADs->SetInfo(); // commit
  1226. } while (0);
  1227. return hr;
  1228. }
  1229. //
  1230. // These methods cover the seperate API to determine whether IntelliMirror
  1231. // caching is enabled. By default, SFM they are disabled.
  1232. //
  1233. // We read this data at level 501 in order to determine whether the target
  1234. // server is NT4. NetShareGetInfo[1005] actually succeeds on an NT4 server,
  1235. // whereas NetShareGetInfo[501] fails with ERROR_INVALID_LEVEL. We want this
  1236. // to fail so that we can disable the checkbox where the underlying
  1237. // functionality is not supported.
  1238. //
  1239. DWORD SmbFileServiceProvider::ReadShareFlags(
  1240. LPCTSTR ptchServerName,
  1241. LPCTSTR ptchShareName,
  1242. DWORD* pdwFlags )
  1243. {
  1244. ASSERT( NULL != pdwFlags );
  1245. if ( !g_SmbDLL.LoadFunctionPointers() )
  1246. {
  1247. ASSERT(FALSE);
  1248. return S_OK;
  1249. }
  1250. *pdwFlags = 0;
  1251. SHARE_INFO_501* pshi501 = NULL;
  1252. NET_API_STATUS retval = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
  1253. const_cast<LPTSTR>(ptchServerName),
  1254. const_cast<LPTSTR>(ptchShareName),
  1255. 501,
  1256. (LPBYTE*)&pshi501);
  1257. if (NERR_Success != retval)
  1258. return retval;
  1259. ASSERT( NULL != pshi501 );
  1260. *pdwFlags = pshi501->shi501_flags;
  1261. FreeData( pshi501 );
  1262. return NERR_Success;
  1263. }
  1264. DWORD SmbFileServiceProvider::WriteShareFlags(
  1265. LPCTSTR ptchServerName,
  1266. LPCTSTR ptchShareName,
  1267. DWORD dwFlags )
  1268. {
  1269. if ( !g_SmbDLL.LoadFunctionPointers() )
  1270. return S_OK;
  1271. SHARE_INFO_1005 shi1005;
  1272. ZeroMemory( &shi1005, sizeof(shi1005) );
  1273. shi1005.shi1005_flags = dwFlags;
  1274. DWORD dwDummy;
  1275. DWORD retval = ((SHARESETINFOPROC)g_SmbDLL[SMB_SHARE_SET_INFO])(
  1276. const_cast<LPTSTR>(ptchServerName),
  1277. const_cast<LPTSTR>(ptchShareName),
  1278. 1005,
  1279. (LPBYTE)&shi1005,
  1280. &dwDummy);
  1281. return retval;
  1282. }
  1283. BOOL SmbFileServiceProvider::GetCachedFlag( DWORD dwFlags, DWORD dwFlagToCheck )
  1284. {
  1285. return (dwFlags & CSC_MASK) == dwFlagToCheck;
  1286. }
  1287. VOID SmbFileServiceProvider::SetCachedFlag( DWORD* pdwFlags, DWORD dwNewFlag )
  1288. {
  1289. *pdwFlags &= ~CSC_MASK;
  1290. *pdwFlags |= dwNewFlag;
  1291. }
  1292. VOID SmbFileServiceProvider::FreeShareProperties(PVOID pvPropertyBlock)
  1293. {
  1294. FreeData( pvPropertyBlock );
  1295. }
  1296. DWORD SmbFileServiceProvider::QueryMaxUsers(PVOID pvPropertyBlock)
  1297. {
  1298. SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pvPropertyBlock;
  1299. ASSERT( NULL != psi2 );
  1300. return psi2->shi2_max_uses;
  1301. }
  1302. VOID SmbFileServiceProvider::SetMaxUsers(PVOID pvPropertyBlock, DWORD dwMaxUsers)
  1303. {
  1304. SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pvPropertyBlock;
  1305. ASSERT( NULL != psi2 );
  1306. psi2->shi2_max_uses = dwMaxUsers;
  1307. }
  1308. VOID SmbFileServiceProvider::FreeData(PVOID pv)
  1309. {
  1310. SMBFreeData( &pv );
  1311. }
  1312. LPCTSTR SmbFileServiceProvider::QueryTransportString()
  1313. {
  1314. return m_strTransportSMB;
  1315. }
  1316. CSmbCookieBlock::~CSmbCookieBlock()
  1317. {
  1318. SMBFreeData( &m_pvCookieData );
  1319. }
  1320. DEFINE_COOKIE_BLOCK(CSmbCookie)
  1321. DEFINE_FORWARDS_MACHINE_NAME( CSmbCookie, m_pCookieBlock )
  1322. void CSmbCookie::AddRefCookie() { m_pCookieBlock->AddRef(); }
  1323. void CSmbCookie::ReleaseCookie() { m_pCookieBlock->Release(); }
  1324. HRESULT CSmbCookie::GetTransport( FILEMGMT_TRANSPORT* pTransport )
  1325. {
  1326. *pTransport = FILEMGMT_SMB;
  1327. return S_OK;
  1328. }
  1329. HRESULT CSmbShareCookie::GetShareName( CString& strShareName )
  1330. {
  1331. SHARE_INFO_2* psi2 = (SHARE_INFO_2*)m_pobject;
  1332. ASSERT( NULL != psi2 );
  1333. strShareName = psi2->shi2_netname;
  1334. return S_OK;
  1335. }
  1336. HRESULT CSmbShareCookie::GetExplorerViewDescription(
  1337. OUT CString& strExplorerViewDescription )
  1338. {
  1339. strExplorerViewDescription = GetShareInfo()->shi2_remark;
  1340. return S_OK;
  1341. }
  1342. HRESULT
  1343. CSmbShareCookie::GetSharePIDList( OUT LPITEMIDLIST *ppidl )
  1344. {
  1345. ASSERT(ppidl);
  1346. ASSERT(NULL == *ppidl); // prevent memory leak
  1347. *ppidl = NULL;
  1348. SHARE_INFO_2* psi2 = (SHARE_INFO_2*)m_pobject;
  1349. ASSERT( NULL != psi2 );
  1350. PCTSTR pszTargetServer = m_pCookieBlock->QueryTargetServer();
  1351. CString csPath;
  1352. if (pszTargetServer)
  1353. {
  1354. if ( _tcslen(pszTargetServer) >= 2 &&
  1355. _T('\\') == *pszTargetServer &&
  1356. _T('\\') == *(pszTargetServer + 1) )
  1357. {
  1358. csPath = pszTargetServer;
  1359. } else
  1360. {
  1361. csPath = _T("\\\\");
  1362. csPath += pszTargetServer;
  1363. }
  1364. csPath += _T("\\");
  1365. csPath += psi2->shi2_netname;
  1366. } else
  1367. {
  1368. csPath = psi2->shi2_path;
  1369. }
  1370. if (FALSE == csPath.IsEmpty())
  1371. *ppidl = ILCreateFromPath(csPath);
  1372. return ((*ppidl) ? S_OK : E_FAIL);
  1373. }
  1374. HRESULT CSmbSessionCookie::GetSessionClientName( CString& strName )
  1375. {
  1376. SESSION_INFO_1* psi1 = (SESSION_INFO_1*)m_pobject;
  1377. ASSERT( NULL != psi1 );
  1378. TranslateIPToComputerName(psi1->sesi1_cname, strName);
  1379. return S_OK;
  1380. }
  1381. HRESULT CSmbSessionCookie::GetSessionUserName( CString& strShareName )
  1382. {
  1383. SESSION_INFO_1* psi1 = (SESSION_INFO_1*)m_pobject;
  1384. ASSERT( NULL != psi1 );
  1385. strShareName = psi1->sesi1_username;
  1386. return S_OK;
  1387. }
  1388. HRESULT CSmbResourceCookie::GetFileID( DWORD* pdwFileID )
  1389. {
  1390. FILE_INFO_3* pfileinfo = (FILE_INFO_3*)m_pobject;
  1391. ASSERT( NULL != pdwFileID && NULL != pfileinfo );
  1392. *pdwFileID = pfileinfo->fi3_id;
  1393. return S_OK;
  1394. }
  1395. BSTR CSmbShareCookie::GetColumnText( int nCol )
  1396. {
  1397. switch (nCol)
  1398. {
  1399. case COLNUM_SHARES_SHARED_FOLDER:
  1400. return GetShareInfo()->shi2_netname;
  1401. case COLNUM_SHARES_SHARED_PATH:
  1402. return GetShareInfo()->shi2_path;
  1403. case COLNUM_SHARES_TRANSPORT:
  1404. return const_cast<BSTR>((LPCTSTR)g_strTransportSMB);
  1405. case COLNUM_SHARES_COMMENT:
  1406. return GetShareInfo()->shi2_remark;
  1407. default:
  1408. ASSERT(FALSE);
  1409. break;
  1410. }
  1411. return L"";
  1412. }
  1413. BSTR CSmbShareCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ )
  1414. {
  1415. if (COLNUM_SHARES_NUM_SESSIONS == nCol)
  1416. return MakeDwordResult( GetNumOfCurrentUses() );
  1417. return GetColumnText(nCol);
  1418. }
  1419. extern CString g_cstrClientName;
  1420. extern CString g_cstrGuest;
  1421. extern CString g_cstrYes;
  1422. extern CString g_cstrNo;
  1423. BSTR CSmbSessionCookie::GetColumnText( int nCol )
  1424. {
  1425. switch (nCol)
  1426. {
  1427. case COLNUM_SESSIONS_USERNAME:
  1428. if ( (GetSessionInfo()->sesi1_user_flags & SESS_GUEST) &&
  1429. ( !(GetSessionInfo()->sesi1_username) ||
  1430. _T('\0') == *(GetSessionInfo()->sesi1_username) ) )
  1431. {
  1432. return const_cast<BSTR>(((LPCTSTR)g_cstrGuest));
  1433. } else
  1434. {
  1435. return GetSessionInfo()->sesi1_username;
  1436. }
  1437. case COLNUM_SESSIONS_COMPUTERNAME:
  1438. {
  1439. TranslateIPToComputerName(GetSessionInfo()->sesi1_cname, g_cstrClientName);
  1440. return const_cast<BSTR>(((LPCTSTR)g_cstrClientName));
  1441. }
  1442. case COLNUM_SESSIONS_TRANSPORT:
  1443. return const_cast<BSTR>((LPCTSTR)g_strTransportSMB);
  1444. case COLNUM_SESSIONS_IS_GUEST:
  1445. if (GetSessionInfo()->sesi1_user_flags & SESS_GUEST)
  1446. return const_cast<BSTR>(((LPCTSTR)g_cstrYes));
  1447. else
  1448. return const_cast<BSTR>(((LPCTSTR)g_cstrNo));
  1449. default:
  1450. ASSERT(FALSE);
  1451. break;
  1452. }
  1453. return L"";
  1454. }
  1455. BSTR CSmbSessionCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ )
  1456. {
  1457. switch (nCol)
  1458. {
  1459. case COLNUM_SESSIONS_NUM_FILES:
  1460. return MakeDwordResult( GetNumOfOpenFiles() );
  1461. case COLNUM_SESSIONS_CONNECTED_TIME:
  1462. return MakeElapsedTimeResult( GetConnectedTime() );
  1463. case COLNUM_SESSIONS_IDLE_TIME:
  1464. return MakeElapsedTimeResult( GetIdleTime() );
  1465. default:
  1466. break;
  1467. }
  1468. return GetColumnText(nCol);
  1469. }
  1470. BSTR CSmbResourceCookie::GetColumnText( int nCol )
  1471. {
  1472. switch (nCol)
  1473. {
  1474. case COLNUM_RESOURCES_FILENAME:
  1475. return GetFileInfo()->fi3_pathname;
  1476. case COLNUM_RESOURCES_USERNAME:
  1477. return GetFileInfo()->fi3_username;
  1478. case COLNUM_RESOURCES_TRANSPORT:
  1479. return const_cast<BSTR>((LPCTSTR)g_strTransportSMB);
  1480. case COLNUM_RESOURCES_OPEN_MODE:
  1481. return MakePermissionsResult( GetFileInfo()->fi3_permissions );
  1482. default:
  1483. ASSERT(FALSE);
  1484. break;
  1485. }
  1486. return L"";
  1487. }
  1488. BSTR CSmbResourceCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ )
  1489. {
  1490. if (COLNUM_RESOURCES_NUM_LOCKS == nCol)
  1491. return MakeDwordResult( GetNumOfLocks() );
  1492. return GetColumnText(nCol);
  1493. }
  1494. CSMBSecurityInformation::CSMBSecurityInformation()
  1495. : m_pvolumeinfo( NULL ),
  1496. m_pDefaultDescriptor( NULL )
  1497. {
  1498. }
  1499. CSMBSecurityInformation::~CSMBSecurityInformation()
  1500. {
  1501. if (NULL != m_pDefaultDescriptor)
  1502. {
  1503. LocalFree(m_pDefaultDescriptor);
  1504. m_pvolumeinfo->shi502_security_descriptor = NULL;
  1505. }
  1506. SMBFreeData( (PVOID*)&m_pvolumeinfo );
  1507. }
  1508. STDMETHODIMP CSMBSecurityInformation::GetSecurity (
  1509. SECURITY_INFORMATION RequestedInformation,
  1510. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  1511. BOOL fDefault )
  1512. {
  1513. MFC_TRY;
  1514. // NOTE: we allow NULL == ppSecurityDescriptor, see SetSecurity
  1515. if (0 == RequestedInformation )
  1516. {
  1517. ASSERT(FALSE);
  1518. return E_INVALIDARG;
  1519. }
  1520. if (fDefault)
  1521. return E_NOTIMPL;
  1522. if ( NULL != ppSecurityDescriptor )
  1523. *ppSecurityDescriptor = NULL;
  1524. if ( !g_SmbDLL.LoadFunctionPointers() )
  1525. {
  1526. ASSERT(FALSE); // NETAPI32 isn't installed?
  1527. return S_OK;
  1528. }
  1529. SMBFreeData( (PVOID*)&m_pvolumeinfo );
  1530. NET_API_STATUS dwErr = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
  1531. QueryMachineName(),
  1532. QueryShareName(),
  1533. 502,
  1534. (LPBYTE*)&m_pvolumeinfo );
  1535. if (NERR_Success != dwErr)
  1536. {
  1537. return HRESULT_FROM_WIN32(dwErr);
  1538. }
  1539. ASSERT(NULL != m_pvolumeinfo);
  1540. if ( NULL == ppSecurityDescriptor )
  1541. return S_OK;
  1542. if (NULL == m_pvolumeinfo->shi502_security_descriptor)
  1543. {
  1544. if (NULL == m_pDefaultDescriptor)
  1545. {
  1546. HRESULT hr = NewDefaultDescriptor(
  1547. &m_pDefaultDescriptor,
  1548. RequestedInformation );
  1549. if ( !SUCCEEDED(hr) )
  1550. return hr;
  1551. }
  1552. m_pvolumeinfo->shi502_security_descriptor = m_pDefaultDescriptor;
  1553. }
  1554. ASSERT( NULL != m_pvolumeinfo->shi502_security_descriptor );
  1555. // We have to pass back a LocalAlloc'ed copy of the SD
  1556. return MakeSelfRelativeCopy(
  1557. m_pvolumeinfo->shi502_security_descriptor,
  1558. ppSecurityDescriptor );
  1559. MFC_CATCH;
  1560. }
  1561. STDMETHODIMP CSMBSecurityInformation::SetSecurity (
  1562. SECURITY_INFORMATION SecurityInformation,
  1563. PSECURITY_DESCRIPTOR pSecurityDescriptor )
  1564. {
  1565. MFC_TRY;
  1566. if ( !g_SmbDLL.LoadFunctionPointers() )
  1567. {
  1568. ASSERT(FALSE); // NETAPI32 isn't installed?
  1569. return S_OK;
  1570. }
  1571. // First get the current settings
  1572. // We call GetSecurity with NULL == ppSecurityDescriptor, this indicates to
  1573. // GetSecurity that it should refresh the shi502 structure but not return
  1574. // a copy of an actual security descriptor.
  1575. HRESULT hr = GetSecurity( SecurityInformation, NULL, FALSE );
  1576. if ( FAILED(hr) )
  1577. return hr;
  1578. // Now set the new values
  1579. m_pvolumeinfo->shi502_security_descriptor = pSecurityDescriptor;
  1580. NET_API_STATUS dwErr = ((SHARESETINFOPROC)g_SmbDLL[SMB_SHARE_SET_INFO])(
  1581. QueryMachineName(),
  1582. QueryShareName(),
  1583. 502,
  1584. (LPBYTE)m_pvolumeinfo,
  1585. NULL );
  1586. if (NERR_Success != dwErr)
  1587. {
  1588. return HRESULT_FROM_WIN32(dwErr);
  1589. }
  1590. return S_OK;
  1591. MFC_CATCH;
  1592. }
  1593. //
  1594. // helper functions
  1595. //
  1596. HRESULT GetDCInfo(
  1597. IN LPCTSTR ptchServerName,
  1598. OUT CString& strDCName
  1599. )
  1600. /*
  1601. Function: retrieve DC name of the domain the server belongs to.
  1602. Return:
  1603. S_OK: if succeeded
  1604. others: if server does not belong to a domain, or error occurred
  1605. */
  1606. {
  1607. strDCName.Empty();
  1608. //
  1609. // get domain name of the server
  1610. //
  1611. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBuffer = NULL;
  1612. DWORD dwErr = DsRoleGetPrimaryDomainInformation(
  1613. ptchServerName,
  1614. DsRolePrimaryDomainInfoBasic,
  1615. (PBYTE *)&pBuffer);
  1616. if (ERROR_SUCCESS != dwErr)
  1617. return HRESULT_FROM_WIN32(dwErr);
  1618. if (pBuffer->MachineRole == DsRole_RoleStandaloneWorkstation ||
  1619. pBuffer->MachineRole == DsRole_RoleStandaloneServer)
  1620. {
  1621. DsRoleFreeMemory(pBuffer);
  1622. return S_FALSE; // server does not belong to a domain
  1623. }
  1624. CString strDomainName = (pBuffer->DomainNameDns ? pBuffer->DomainNameDns : pBuffer->DomainNameFlat);
  1625. DsRoleFreeMemory(pBuffer);
  1626. if (!strDomainName)
  1627. return E_OUTOFMEMORY;
  1628. if (strDomainName.IsEmpty())
  1629. return S_FALSE; // something is wrong, treat it as server does not belong to a domain
  1630. //
  1631. // In case the DNS name is in absolute form, remove the ending dot
  1632. //
  1633. int nlen = strDomainName.GetLength();
  1634. if ( _T('.') == strDomainName[nlen - 1] )
  1635. strDomainName.SetAt(nlen - 1, _T('\0'));
  1636. //
  1637. // get DC name of that domain
  1638. //
  1639. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  1640. dwErr = DsGetDcName(
  1641. NULL, // Run on Current Server.
  1642. strDomainName,
  1643. NULL,
  1644. NULL,
  1645. DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_DNS_NAME,
  1646. &pDCInfo
  1647. );
  1648. if (ERROR_SUCCESS != dwErr)
  1649. return HRESULT_FROM_WIN32(dwErr);
  1650. if ( _T('\\') == *(pDCInfo->DomainControllerName) )
  1651. strDCName = pDCInfo->DomainControllerName + 2;
  1652. else
  1653. strDCName = pDCInfo->DomainControllerName;
  1654. NetApiBufferFree(pDCInfo);
  1655. if (!strDCName)
  1656. return E_OUTOFMEMORY;
  1657. return S_OK;
  1658. }
  1659. HRESULT GetADsPathOfComputerObject(
  1660. IN LPCTSTR ptchServerName,
  1661. OUT CString& strADsPath,
  1662. OUT CString& strDCName
  1663. )
  1664. /*
  1665. Function: retrieve LDAP://<DC>/<FQDN of computer object>.
  1666. Return:
  1667. S_OK: if succeeded
  1668. others: if server does not belong to a domain, or error occurred
  1669. */
  1670. {
  1671. //
  1672. // Get NT4 account name for this server
  1673. //
  1674. PWKSTA_INFO_100 wki100 = NULL;
  1675. NET_API_STATUS NetStatus = NetWkstaGetInfo((LPTSTR)ptchServerName, 100, (LPBYTE *)&wki100 );
  1676. if (ERROR_SUCCESS != NetStatus)
  1677. return HRESULT_FROM_WIN32(NetStatus);
  1678. HRESULT hr = S_FALSE;
  1679. CString strNT4Name;
  1680. if (wki100->wki100_langroup)
  1681. {
  1682. strNT4Name = wki100->wki100_langroup;
  1683. strNT4Name += _T("\\");
  1684. strNT4Name += wki100->wki100_computername;
  1685. strNT4Name += _T("$");
  1686. hr = S_OK;
  1687. }
  1688. NetApiBufferFree((LPBYTE)wki100);
  1689. if (S_OK != hr)
  1690. return hr;
  1691. //
  1692. // get DC name of the server's domain
  1693. //
  1694. hr = GetDCInfo(ptchServerName, strDCName);
  1695. if (S_OK != hr)
  1696. return hr;
  1697. //
  1698. // get computerDN
  1699. //
  1700. CComPtr<IADsNameTranslate> spiADsNameTranslate;
  1701. hr = CoCreateInstance(CLSID_NameTranslate, NULL, CLSCTX_INPROC_SERVER, IID_IADsNameTranslate, (void **)&spiADsNameTranslate);
  1702. if (FAILED(hr)) return hr;
  1703. hr = spiADsNameTranslate->Init(ADS_NAME_INITTYPE_SERVER, (LPTSTR)(LPCTSTR)strDCName);
  1704. if (FAILED(hr)) return hr;
  1705. hr = spiADsNameTranslate->Set(ADS_NAME_TYPE_NT4, (LPTSTR)(LPCTSTR)strNT4Name);
  1706. if (FAILED(hr)) return hr;
  1707. CComBSTR sbstrComputerDN;
  1708. hr = spiADsNameTranslate->Get(ADS_NAME_TYPE_1779, &sbstrComputerDN);
  1709. if (FAILED(hr)) return hr;
  1710. strADsPath = _T("LDAP://");
  1711. strADsPath += strDCName;
  1712. strADsPath += _T("/");
  1713. strADsPath += sbstrComputerDN;
  1714. return hr;
  1715. }
  1716. HRESULT CheckSchemaVersion(IN LPCTSTR ptchServerName)
  1717. /*
  1718. Function: check if the schema allows volume object be created as child of computer object.
  1719. Return:
  1720. S_OK: yes, it's the new schema, it allows
  1721. S_FALSE: it doesn't allow, or the server doesn't belong to a domain at all
  1722. others: error occurred
  1723. */
  1724. {
  1725. HRESULT hr = S_OK;
  1726. //
  1727. // get DC name of the server's domain
  1728. //
  1729. CString strDCName;
  1730. hr = GetDCInfo(ptchServerName, strDCName);
  1731. if (S_OK != hr)
  1732. return hr;
  1733. //
  1734. // Get schema naming context from the rootDSE.
  1735. //
  1736. CComPtr<IADs> spiRootADs;
  1737. hr = ADsGetObject(_T("LDAP://rootDSE"),
  1738. IID_IADs,
  1739. (void**)&spiRootADs);
  1740. if (SUCCEEDED(hr))
  1741. {
  1742. VARIANT var;
  1743. VariantInit(&var);
  1744. hr = spiRootADs->Get(_T("schemaNamingContext"), &var);
  1745. if (FAILED(hr)) return hr;
  1746. //
  1747. // get LDAP path to the schema of Connection-Point class
  1748. //
  1749. CString strADsPath = _T("LDAP://");
  1750. strADsPath += strDCName;
  1751. strADsPath += _T("/CN=Connection-Point,");
  1752. strADsPath += V_BSTR(&var);
  1753. VariantClear(&var);
  1754. CComPtr<IADs> spiADs;
  1755. hr = ADsGetObject(strADsPath, IID_IADs, (void**)&spiADs);
  1756. if (FAILED(hr)) return hr;
  1757. VariantInit(&var);
  1758. hr = spiADs->Get(_T("systemPossSuperiors"), &var);
  1759. if (SUCCEEDED(hr))
  1760. {
  1761. hr = IsValueInVarArray(&var, _T("computer"));
  1762. VariantClear(&var);
  1763. } else if (E_ADS_PROPERTY_NOT_FOUND == hr)
  1764. hr = S_FALSE;
  1765. }
  1766. return hr;
  1767. }
  1768. BOOL CheckPolicyOnSharePublish(IN LPCTSTR ptchShareName)
  1769. {
  1770. if (!ptchShareName && !*ptchShareName)
  1771. return FALSE; // invalid share name
  1772. //
  1773. // no publish page on hidden shares
  1774. //
  1775. int len = lstrlen(ptchShareName);
  1776. if (_T('$') == *(ptchShareName + len - 1))
  1777. return FALSE;
  1778. //
  1779. // no publish page on system shares
  1780. //
  1781. int n = sizeof(g_pszSystemShares) / sizeof(LPCTSTR);
  1782. for (int i = 0; i < n; i++)
  1783. {
  1784. if (!lstrcmpi(ptchShareName, g_pszSystemShares[i]))
  1785. return FALSE;
  1786. }
  1787. //
  1788. // check group policy
  1789. //
  1790. BOOL bAddPublishPage = TRUE; // by default, we display the share publish page
  1791. HKEY hKey = NULL;
  1792. DWORD dwType = 0;
  1793. DWORD dwData = 0;
  1794. DWORD cbData = sizeof(dwData);
  1795. LONG lErr = RegOpenKeyEx(
  1796. HKEY_CURRENT_USER,
  1797. _T("Software\\Policies\\Microsoft\\Windows NT\\SharedFolders"),
  1798. 0,
  1799. KEY_QUERY_VALUE,
  1800. &hKey);
  1801. if (ERROR_SUCCESS == lErr)
  1802. {
  1803. lErr = RegQueryValueEx(hKey, _T("PublishSharedFolders"), 0, &dwType, (LPBYTE)&dwData, &cbData);
  1804. if (ERROR_SUCCESS == lErr &&
  1805. REG_DWORD == dwType &&
  1806. 0 == dwData) // policy is disabled
  1807. bAddPublishPage = FALSE;
  1808. RegCloseKey(hKey);
  1809. }
  1810. return bAddPublishPage;
  1811. }
  1812. void mystrtok(
  1813. IN LPCTSTR pszString,
  1814. IN OUT int* pnIndex, // start from 0
  1815. IN LPCTSTR pszCharSet,
  1816. OUT CString& strToken
  1817. )
  1818. {
  1819. strToken.Empty();
  1820. if (!pszString || !*pszString ||
  1821. !pszCharSet || !pnIndex ||
  1822. *pnIndex >= lstrlen(pszString))
  1823. {
  1824. return;
  1825. }
  1826. TCHAR *ptchStart = (PTSTR)pszString + *pnIndex;
  1827. if (!*pszCharSet)
  1828. {
  1829. strToken = ptchStart;
  1830. return;
  1831. }
  1832. //
  1833. // move p to the 1st char of the token
  1834. //
  1835. TCHAR *p = ptchStart;
  1836. while (*p)
  1837. {
  1838. if (_tcschr(pszCharSet, *p))
  1839. p++;
  1840. else
  1841. break;
  1842. }
  1843. ptchStart = p; // adjust ptchStart to point at the 1st char of the token
  1844. //
  1845. // move p to the char after the last char of the token
  1846. //
  1847. while (*p)
  1848. {
  1849. if (_tcschr(pszCharSet, *p))
  1850. break;
  1851. else
  1852. p++;
  1853. }
  1854. //
  1855. // ptchStart: points at the 1st char of the token
  1856. // p: points at the char after the last char of the token
  1857. //
  1858. if (ptchStart != p)
  1859. {
  1860. strToken = CString(ptchStart, (int)(p - ptchStart));
  1861. *pnIndex = (int)(p - pszString);
  1862. }
  1863. // return
  1864. }
  1865. //
  1866. // write a semi-colon separated string into a VARIANT
  1867. //
  1868. HRESULT PutMultiValuesIntoVarArray(
  1869. IN LPCTSTR pszValues,
  1870. OUT VARIANT* pVar
  1871. )
  1872. {
  1873. if (!pVar || !pszValues || !*pszValues)
  1874. return E_INVALIDARG;
  1875. //
  1876. // get count of items
  1877. //
  1878. int nCount = 0;
  1879. int nIndex = 0;
  1880. CString strToken;
  1881. mystrtok(pszValues, &nIndex, _T(";"), strToken);
  1882. while (!strToken.IsEmpty())
  1883. {
  1884. nCount++;
  1885. mystrtok(pszValues, &nIndex, _T(";"), strToken);
  1886. }
  1887. if (!nCount)
  1888. return E_INVALIDARG;
  1889. //
  1890. // create an array of variants to hold all the data
  1891. //
  1892. SAFEARRAYBOUND bounds = {nCount, 0};
  1893. SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
  1894. VARIANT* varArray;
  1895. SafeArrayAccessData(psa, (void**)&varArray);
  1896. nCount = 0;
  1897. nIndex = 0;
  1898. mystrtok(pszValues, &nIndex, _T(";"), strToken);
  1899. while (!strToken.IsEmpty())
  1900. {
  1901. strToken.TrimLeft();
  1902. strToken.TrimRight();
  1903. VariantInit(&(varArray[nCount]));
  1904. varArray[nCount].vt = VT_BSTR;
  1905. varArray[nCount].bstrVal = SysAllocString(strToken);
  1906. nCount++;
  1907. mystrtok(pszValues, &nIndex, _T(";"), strToken);
  1908. }
  1909. SafeArrayUnaccessData(psa);
  1910. //
  1911. // return the variant array
  1912. //
  1913. VariantInit(pVar);
  1914. pVar->vt = VT_ARRAY | VT_VARIANT;
  1915. pVar->parray = psa;
  1916. return S_OK;
  1917. }
  1918. //
  1919. // read a multi-valued VARIANT into a semicolon separated string
  1920. //
  1921. HRESULT GetSingleOrMultiValuesFromVarArray(
  1922. IN VARIANT* pVar,
  1923. OUT CString& strValues
  1924. )
  1925. {
  1926. strValues.Empty();
  1927. if (V_VT(pVar) != VT_BSTR &&
  1928. V_VT(pVar) != (VT_ARRAY | VT_VARIANT))
  1929. return E_INVALIDARG;
  1930. if (V_VT(pVar) == VT_BSTR)
  1931. {
  1932. strValues = V_BSTR(pVar);
  1933. } else
  1934. {
  1935. LONG lstart, lend;
  1936. SAFEARRAY *sa = V_ARRAY(pVar);
  1937. VARIANT varItem;
  1938. SafeArrayGetLBound(sa, 1, &lstart);
  1939. SafeArrayGetUBound(sa, 1, &lend);
  1940. VariantInit(&varItem);
  1941. for (LONG i = lstart; i <= lend; i++)
  1942. {
  1943. SafeArrayGetElement(sa, &i, &varItem);
  1944. if (!strValues.IsEmpty())
  1945. strValues += _T(";");
  1946. strValues += V_BSTR(&varItem);
  1947. VariantClear(&varItem);
  1948. }
  1949. }
  1950. return S_OK;
  1951. }
  1952. HRESULT IsValueInVarArray(
  1953. IN VARIANT* pVar,
  1954. IN LPCTSTR ptchValue
  1955. )
  1956. {
  1957. if (V_VT(pVar) != VT_BSTR &&
  1958. V_VT(pVar) != (VT_ARRAY | VT_VARIANT))
  1959. return E_INVALIDARG;
  1960. HRESULT hr = S_FALSE;
  1961. if (V_VT(pVar) == VT_BSTR)
  1962. {
  1963. if (!lstrcmpi(ptchValue, V_BSTR(pVar)))
  1964. hr = S_OK;
  1965. } else
  1966. {
  1967. LONG lstart, lend;
  1968. SAFEARRAY *sa = V_ARRAY(pVar);
  1969. VARIANT varItem;
  1970. SafeArrayGetLBound(sa, 1, &lstart);
  1971. SafeArrayGetUBound(sa, 1, &lend);
  1972. VariantInit(&varItem);
  1973. for (LONG i = lstart; (i <= lend) && (S_FALSE == hr); i++)
  1974. {
  1975. SafeArrayGetElement(sa, &i, &varItem);
  1976. if (!lstrcmpi(ptchValue, V_BSTR(&varItem)))
  1977. hr = S_OK;
  1978. VariantClear(&varItem);
  1979. }
  1980. }
  1981. return hr;
  1982. }
  1983. /*
  1984. We block the operation if:
  1985. A) You are monitoring a remote computer, not the local one
  1986. B) The session username matches the currently logged on user
  1987. C) The number of files opened on the server is greater than 0
  1988. D) The client name is either one of our IP addresses or our ComputerName.
  1989. */
  1990. BOOL BlockRemoteAdminSession(
  1991. IN PCTSTR i_pszTargetServer,
  1992. IN PCTSTR i_pszClientName,
  1993. IN PCTSTR i_pszUserName,
  1994. IN DWORD i_dwNumOpenSessions
  1995. )
  1996. {
  1997. if (!i_pszClientName || !i_pszUserName)
  1998. return FALSE;
  1999. // if we're monitoring the local machine
  2000. if (!i_pszTargetServer || !*i_pszTargetServer)
  2001. return FALSE;
  2002. // if number of sessions is not greater than 0
  2003. if (0 == i_dwNumOpenSessions)
  2004. return FALSE;
  2005. // get username, return if user name doesn't match
  2006. TCHAR szUser[UNLEN+1] = _T("");
  2007. DWORD dwSize = UNLEN+1;
  2008. GetUserName(szUser, &dwSize);
  2009. if (lstrcmpi(szUser, i_pszUserName))
  2010. return FALSE;
  2011. // compare with local computer's name
  2012. TCHAR tszComputer[MAX_COMPUTERNAME_LENGTH + 1] = _T("");
  2013. dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  2014. GetComputerName(tszComputer, &dwSize);
  2015. BOOL bMatch = (0 == lstrcmpi(tszComputer, i_pszClientName));
  2016. // compare with each IP address of the local computer
  2017. if (!bMatch)
  2018. {
  2019. // convert WCHAR to char
  2020. int iBytes = 0;
  2021. char szComputer[MAX_COMPUTERNAME_LENGTH + 1] = "";
  2022. char szClientName[MAX_COMPUTERNAME_LENGTH + 1] = "";
  2023. #if defined UNICODE
  2024. iBytes = MAX_COMPUTERNAME_LENGTH + 1;
  2025. WideCharToMultiByte(CP_ACP, 0, tszComputer, -1, szComputer, iBytes, NULL, NULL);
  2026. iBytes = MAX_COMPUTERNAME_LENGTH + 1;
  2027. WideCharToMultiByte(CP_ACP, 0, i_pszClientName, -1, szClientName, iBytes, NULL, NULL);
  2028. #else
  2029. lstrcpy(szComputer, tszComputer);
  2030. lstrcpy(szClientName, i_pszClientName);
  2031. #endif
  2032. WORD wVersionRequested = MAKEWORD( 2, 2 );
  2033. WSADATA wsaData = {0};
  2034. int err = WSAStartup( wVersionRequested, &wsaData );
  2035. if (err == 0)
  2036. {
  2037. struct hostent *pHostEnt = gethostbyname(szComputer);
  2038. if (pHostEnt)
  2039. {
  2040. struct in_addr IPAddr = {0};
  2041. PSTR pszIP = NULL;
  2042. int i = 0;
  2043. while (pHostEnt->h_addr_list[i])
  2044. {
  2045. memcpy(&IPAddr, pHostEnt->h_addr_list[i++], pHostEnt->h_length);
  2046. pszIP = inet_ntoa(IPAddr);
  2047. if (!_stricmp(pszIP, szClientName))
  2048. {
  2049. bMatch = TRUE;
  2050. break;
  2051. }
  2052. }
  2053. }
  2054. WSACleanup( );
  2055. }
  2056. }
  2057. // keep this session for remote admin purpose
  2058. if (bMatch)
  2059. DoErrMsgBox(GetActiveWindow(), MB_OK, 0, IDS_POPUP_REMOTEADMINSESSION);
  2060. return bMatch;
  2061. }
  2062. /*
  2063. We block the operation if:
  2064. A) You are monitoring a remote computer, not the local one
  2065. B) The openfile pathname matches \PIPE\srvsvc or \PIPE\MacFile
  2066. C) The openfile username matches the currently logged on user
  2067. */
  2068. BOOL BlockRemoteAdminFile(
  2069. IN PCTSTR i_pszTargetServer,
  2070. IN PCTSTR i_pszPathName,
  2071. IN PCTSTR i_pszUserName
  2072. )
  2073. {
  2074. if (!i_pszPathName || !i_pszUserName)
  2075. return FALSE;
  2076. // if we're monitoring the local machine
  2077. if (!i_pszTargetServer || !*i_pszTargetServer)
  2078. return FALSE;
  2079. if (lstrcmpi(_T("\\PIPE\\srvsvc"), i_pszPathName) && lstrcmpi(_T("\\PIPE\\MacFile"), i_pszPathName))
  2080. return FALSE;
  2081. // get username, return if user name doesn't match
  2082. TCHAR szUser[UNLEN+1] = _T("");
  2083. DWORD dwSize = UNLEN+1;
  2084. GetUserName(szUser, &dwSize);
  2085. if (lstrcmpi(szUser, i_pszUserName))
  2086. return FALSE;
  2087. // this is the admin named pipe, keep it for remote admin purpose
  2088. DoErrMsgBox(GetActiveWindow(), MB_OK, 0, IDS_POPUP_REMOTEADMINFILE, i_pszPathName);
  2089. return TRUE;
  2090. }
  2091. void TranslateIPToComputerName(LPCTSTR ptszIP, CString& strName)
  2092. {
  2093. int iBytes = 0;
  2094. char szIP[MAX_PATH] = "";
  2095. #if defined UNICODE
  2096. iBytes = MAX_PATH;
  2097. WideCharToMultiByte(CP_ACP, 0, ptszIP, -1, szIP, iBytes, NULL, NULL);
  2098. #else
  2099. lstrcpy(szIP, ptszIP);
  2100. #endif
  2101. strName = ptszIP;
  2102. ULONG inaddr = inet_addr(szIP);
  2103. if (INADDR_NONE != inaddr)
  2104. {
  2105. struct hostent *pHostEnt = gethostbyaddr((char *)&inaddr, sizeof(inaddr), AF_INET);
  2106. if (pHostEnt)
  2107. {
  2108. #if defined UNICODE
  2109. DWORD cb = MultiByteToWideChar(CP_ACP, 0, pHostEnt->h_name, -1, NULL, 0);
  2110. strName = CString(_T('0'), cb);
  2111. LPTSTR ptszName = strName.GetBuffer(cb);
  2112. MultiByteToWideChar(CP_ACP, 0, pHostEnt->h_name, -1, ptszName, cb);
  2113. strName.ReleaseBuffer();
  2114. #else
  2115. strName = pHostEnt->h_name;
  2116. #endif
  2117. }
  2118. }
  2119. }