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.

476 lines
15 KiB

  1. //
  2. // Sharing.cpp
  3. //
  4. // Utility functions to help with file and printer sharing.
  5. //
  6. // To use these functions, you need to add SvrApi.cpp to your project,
  7. // and call its InitSvrApiThunk() function at startup.
  8. //
  9. // History:
  10. //
  11. // 5/17/1999 KenSh Created for JetNet
  12. // 10/05/1999 KenSh Adapted for Home Networking Wizard
  13. // 10/19/1999 KenSh Added AreAdvancedFoldersShared
  14. //
  15. #include "stdafx.h"
  16. #include "Sharing.h"
  17. #include "MySvrApi.h"
  18. #include "MyDocs.h"
  19. #include "Util.h"
  20. #include <regstr.h>
  21. #include <lm.h>
  22. #include "theapp.h"
  23. #include "newapi.h"
  24. #include <msshrui.h> // SetFolderPermissionsForSharing
  25. #define NET_API_STATUS DWORD
  26. #define API_RET_TYPE NET_API_STATUS
  27. // Allocates array of shares using malloc(), returns number of shares
  28. int EnumLocalShares(SHARE_INFO** pprgShares)
  29. {
  30. SHARE_INFO_502* prgShares = NULL;
  31. DWORD dwShares;
  32. DWORD dwTotalShares;
  33. if (NERR_Success == NetShareEnum(NULL, 502, (LPBYTE*)&prgShares, MAX_PREFERRED_LENGTH, &dwShares, &dwTotalShares, NULL))
  34. {
  35. // We defined SHARE_INFO to mimic SHARE_INFO_502, even though we ignore
  36. // all but four fields of it.
  37. *pprgShares = (SHARE_INFO*)prgShares;
  38. return (int)dwShares;
  39. }
  40. else
  41. {
  42. *pprgShares = NULL;
  43. return 0;
  44. }
  45. }
  46. // EnumSharedDrives
  47. //
  48. // Use this version if you've already enumerated shares via EnumLocalShares().
  49. //
  50. // pbDriveArray is an array of 26 bytes, one for each possible shared drive.
  51. // Each entry is filled with a NETACCESS flag (defined in Sharing.h): 0 if not
  52. // shared, 1 if read-only, 2 if read-write, 3 if depends-on-password.
  53. //
  54. // Return value is number of drives shared.
  55. //
  56. int EnumSharedDrives(LPBYTE pbDriveArray, int cShares, const SHARE_INFO* prgShares)
  57. {
  58. ZeroMemory(pbDriveArray, 26);
  59. int cDrives = 0;
  60. for (int i = 0; i < cShares; i++)
  61. {
  62. LPCTSTR pszPath = prgShares[i].pszPath;
  63. if (pszPath[1] == _T(':') && pszPath[2] == _T('\\')) // is it a folder
  64. {
  65. if (pszPath[3] == _T('\0')) // is it a whole drive
  66. {
  67. TCHAR ch = (TCHAR)CharUpper((LPTSTR)(prgShares[i].pszPath[0]));
  68. ASSERT (ch >= _T('A') && ch <= _T('Z'));
  69. pbDriveArray[ch - _T('A')] = (BYTE)(prgShares[i].uFlags & NETACCESS_MASK);
  70. cDrives += 1;
  71. }
  72. }
  73. }
  74. return cDrives;
  75. }
  76. // Use this version of EnumSharedDrives if you haven't called EnumLocalShares()
  77. int EnumSharedDrives(LPBYTE pbDriveArray)
  78. {
  79. SHARE_INFO* prgShares;
  80. int cShares = EnumLocalShares(&prgShares);
  81. int cDrives = EnumSharedDrives(pbDriveArray, cShares, prgShares);
  82. NetApiBufferFree(prgShares);
  83. return cDrives;
  84. }
  85. // Helper function for ShareFolder() (and SharePrinter on 9x)
  86. BOOL ShareHelper(LPCTSTR pszPath, LPCTSTR pszShareName, DWORD dwAccess, BYTE bShareType, LPCTSTR pszReadOnlyPassword, LPCTSTR pszFullAccessPassword)
  87. {
  88. ASSERTMSG(pszReadOnlyPassword==NULL, "ShareHelper doesn't support roPassword");
  89. SHARE_INFO_502 si;
  90. si.shi502_netname = (LPTSTR)pszShareName;
  91. //CharUpperA(si.shi50_netname);
  92. si.shi502_type = bShareType;
  93. si.shi502_remark = NULL;
  94. si.shi502_permissions = ACCESS_ALL;
  95. si.shi502_max_uses = -1;
  96. si.shi502_current_uses = -1;
  97. TCHAR szPath[MAX_PATH];
  98. if (bShareType == STYPE_DISKTREE)
  99. {
  100. StrCpyN(szPath, pszPath, ARRAYSIZE(szPath));
  101. CharUpper(szPath);
  102. si.shi502_path = szPath;
  103. }
  104. else
  105. {
  106. si.shi502_path = (LPWSTR)pszPath;
  107. }
  108. si.shi502_passwd = (pszFullAccessPassword) ? (LPTSTR)pszFullAccessPassword : L"";
  109. si.shi502_reserved = NULL;
  110. si.shi502_security_descriptor = NULL;
  111. if (NO_ERROR != NetShareAdd(NULL, 502, (LPBYTE)&si))
  112. {
  113. return FALSE;
  114. }
  115. MakeSharePersistent(pszShareName);
  116. return TRUE;
  117. }
  118. // dwAccess is NETACCESS_READONLY, NETACCESS_FULL, or NETACCESS_DEPENDSON
  119. // Either or both passwords may be NULL. For simplicity, you can pass the
  120. // same password for both, even if you're only sharing read-only or full-access.
  121. BOOL ShareFolder(LPCTSTR pszPath, LPCTSTR pszShareName, DWORD dwAccess, LPCTSTR pszReadOnlyPassword, LPCTSTR pszFullAccessPassword)
  122. {
  123. ASSERT(pszPath != NULL);
  124. ASSERT(pszShareName != NULL);
  125. ASSERT(dwAccess == NETACCESS_READONLY || dwAccess == NETACCESS_FULL || dwAccess == NETACCESS_DEPENDSON);
  126. BOOL bResult = ShareHelper(pszPath, pszShareName, dwAccess, STYPE_DISKTREE, pszReadOnlyPassword, pszFullAccessPassword);
  127. if (bResult)
  128. {
  129. SHChangeNotify(SHCNE_NETSHARE, SHCNF_PATH, pszPath, NULL);
  130. // On NT, make sure the folder permissions are set correctly
  131. HINSTANCE hInstNtShrUI = LoadLibrary(TEXT("ntshrui.dll"));
  132. if (hInstNtShrUI != NULL)
  133. {
  134. PFNSETFOLDERPERMISSIONSFORSHARING pfn = (PFNSETFOLDERPERMISSIONSFORSHARING)GetProcAddress(hInstNtShrUI, "SetFolderPermissionsForSharing");
  135. if (pfn != NULL)
  136. {
  137. // level 3 means "shared read/write"
  138. // level 2 means "shared read-only"
  139. (*pfn)(pszPath, NULL, dwAccess == NETACCESS_FULL ? 3 : 2, NULL);
  140. }
  141. FreeLibrary(hInstNtShrUI);
  142. }
  143. }
  144. return bResult;
  145. }
  146. BOOL UnshareFolder(LPCTSTR pszPath)
  147. {
  148. TCHAR szShareName[SHARE_NAME_LENGTH+1];
  149. BOOL bResult = FALSE;
  150. if (ShareNameFromPath(pszPath, szShareName, ARRAYSIZE(szShareName)))
  151. {
  152. if (NO_ERROR == NetShareDel(NULL, szShareName, 0))
  153. {
  154. SHChangeNotify(SHCNE_NETUNSHARE, SHCNF_PATH, pszPath, NULL);
  155. bResult = TRUE;
  156. // On NT, make sure the folder permissions are set correctly
  157. HINSTANCE hInstNtShrUI = LoadLibrary(TEXT("ntshrui.dll"));
  158. if (hInstNtShrUI != NULL)
  159. {
  160. PFNSETFOLDERPERMISSIONSFORSHARING pfn = (PFNSETFOLDERPERMISSIONSFORSHARING)GetProcAddress(hInstNtShrUI, "SetFolderPermissionsForSharing");
  161. if (pfn != NULL)
  162. {
  163. // level 1 means "not shared"
  164. (*pfn)(pszPath, NULL, 1, NULL);
  165. }
  166. FreeLibrary(hInstNtShrUI);
  167. }
  168. }
  169. }
  170. return bResult;
  171. }
  172. BOOL ShareNameFromPath(LPCTSTR pszPath, LPTSTR pszShareName, UINT cchShareName)
  173. {
  174. BOOL bResult = FALSE;
  175. *pszShareName = _T('\0');
  176. SHARE_INFO* prgShares;
  177. int cShares = EnumLocalShares(&prgShares);
  178. for (int i = 0; i < cShares; i++)
  179. {
  180. if (0 == StrCmpI(prgShares[i].pszPath, pszPath))
  181. {
  182. StrCpyN(pszShareName, prgShares[i].szShareName, cchShareName);
  183. bResult = TRUE;
  184. break;
  185. }
  186. }
  187. NetApiBufferFree(prgShares);
  188. return bResult;
  189. }
  190. BOOL IsVisibleFolderShare(const SHARE_INFO* pShare)
  191. {
  192. return (pShare->bShareType == STYPE_DISKTREE &&
  193. pShare->szShareName[lstrlen(pShare->szShareName) - 1] != _T('$'));
  194. }
  195. BOOL IsShareNameInUse(LPCTSTR pszShareName)
  196. {
  197. LPBYTE pbuf;
  198. BOOL bResult = (NERR_Success == NetShareGetInfo(NULL, pszShareName, 502, &pbuf));
  199. if (bResult)
  200. NetApiBufferFree(pbuf);
  201. return bResult;
  202. }
  203. // Note: this function works for printers too
  204. BOOL IsFolderSharedEx(LPCTSTR pszPath, BOOL bDetectHidden, BOOL bPrinter, int cShares, const SHARE_INFO* prgShares)
  205. {
  206. BYTE bShareType = (bPrinter ? STYPE_PRINTQ : STYPE_DISKTREE);
  207. for (int i = 0; i < cShares; i++)
  208. {
  209. const SHARE_INFO* pShare = &prgShares[i];
  210. if (pShare->bShareType == bShareType &&
  211. (bDetectHidden || IsVisibleFolderShare(pShare)) &&
  212. 0 == StrCmpI(pShare->pszPath, pszPath))
  213. {
  214. return TRUE;
  215. }
  216. }
  217. return FALSE;
  218. }
  219. BOOL IsFolderShared(LPCTSTR pszPath, BOOL bDetectHidden)
  220. {
  221. SHARE_INFO* prgShares;
  222. int cShares = EnumLocalShares(&prgShares);
  223. BOOL bShared = IsFolderSharedEx(pszPath, bDetectHidden, FALSE, cShares, prgShares);
  224. NetApiBufferFree(prgShares);
  225. return bShared;
  226. }
  227. void MakeSharePersistent(LPCTSTR pszShareName)
  228. {
  229. SHARE_INFO_502* pShare2;
  230. if (GetShareInfo502(pszShareName, &pShare2))
  231. {
  232. SetShareInfo502(pShare2->shi502_netname, pShare2);
  233. // Need to manually add the Path to the registry
  234. CRegistry reg;
  235. if (reg.OpenKey(HKEY_LOCAL_MACHINE, REGSTR_KEY_SHARES))
  236. {
  237. if (reg.OpenSubKey(pShare2->shi502_netname))
  238. {
  239. reg.SetStringValue(REGSTR_VAL_SHARES_PATH, pShare2->shi502_path);
  240. }
  241. else if (reg.OpenKey(HKEY_LOCAL_MACHINE, REGSTR_KEY_SHARES) && reg.CreateSubKey(pShare2->shi502_netname))
  242. {
  243. // On older downlevel platforms we need to persist this manually.
  244. DWORD dwFlags = (pShare2->shi502_permissions & (ACCESS_ALL ^ ACCESS_READ)) ? SHI50F_FULL : SHI50F_RDONLY;
  245. dwFlags |= SHI50F_PERSIST;
  246. if (pShare2->shi502_type == STYPE_PRINTQ)
  247. dwFlags |= 0x0090; // REVIEW: what does this number mean?
  248. else
  249. dwFlags |= 0x0080; // REVIEW: what does this number mean?
  250. reg.SetDwordValue(REGSTR_VAL_SHARES_FLAGS, dwFlags);
  251. reg.SetDwordValue(REGSTR_VAL_SHARES_TYPE, (DWORD)pShare2->shi502_type);
  252. reg.SetStringValue(REGSTR_VAL_SHARES_PATH, pShare2->shi502_path);
  253. reg.SetStringValue(REGSTR_VAL_SHARES_REMARK, pShare2->shi502_remark);
  254. }
  255. }
  256. NetApiBufferFree(pShare2);
  257. }
  258. #ifdef OLD_WAY
  259. // Hack: add the new share to the registry, or else it won't be persisted!
  260. // REVIEW: surely there must be an API that does this??
  261. CRegistry reg;
  262. if (reg.OpenKey(HKEY_LOCAL_MACHINE, REGSTR_KEY_SHARES))
  263. {
  264. if (reg.CreateSubKey(pShare->szShareName) ||
  265. reg.OpenSubKey(pShare->szShareName))
  266. {
  267. DWORD dwFlags = pShare->uFlags | SHI50F_PERSIST;
  268. if (pShare->bShareType == STYPE_PRINTQ)
  269. dwFlags |= 0x0090; // REVIEW: what does this number mean?
  270. else
  271. dwFlags |= 0x0080; // REVIEW: what does this number mean?
  272. reg.SetDwordValue(REGSTR_VAL_SHARES_FLAGS, dwFlags);
  273. reg.SetDwordValue(REGSTR_VAL_SHARES_TYPE, (DWORD)pShare->bShareType);
  274. reg.SetStringValue(REGSTR_VAL_SHARES_PATH, pShare->pszPath);
  275. reg.SetStringValue(REGSTR_VAL_SHARES_REMARK, pShare->pszComment);
  276. reg.SetStringValue(REGSTR_VAL_SHARES_RW_PASS, pShare->szPassword_rw);
  277. reg.SetStringValue(REGSTR_VAL_SHARES_RO_PASS, pShare->szPassword_ro);
  278. // reg.SetBinaryValue("Parm1enc", "", 0);
  279. // reg.SetBinaryValue("Parm2enc", "", 0);
  280. // Note: passwords are encrypted next time the user reboots.
  281. }
  282. }
  283. #endif // OLD_WAY
  284. }
  285. BOOL SetShareInfo502(LPCTSTR pszShareName, SHARE_INFO_502* pShare)
  286. {
  287. BOOL bResult;
  288. if (StrCmpI(pszShareName, pShare->shi502_netname) != 0)
  289. {
  290. // Can't rename an existing share. Unshare and re-share instead.
  291. bResult = (NO_ERROR == NetShareDel(NULL, pszShareName, 0) &&
  292. NO_ERROR == NetShareAdd(NULL, 502, (LPBYTE)pShare));
  293. if (bResult)
  294. {
  295. MakeSharePersistent(pShare->shi502_netname);
  296. }
  297. }
  298. else
  299. {
  300. // Change parameters of existing share.
  301. bResult = (NO_ERROR == NetShareSetInfo(NULL, pszShareName, 502, (LPBYTE)pShare));
  302. }
  303. return bResult;
  304. }
  305. BOOL GetShareInfo502(LPCTSTR pszShareName, SHARE_INFO_502** ppShare)
  306. {
  307. NET_API_STATUS ret = NetShareGetInfo(NULL, pszShareName, 502, (LPBYTE*)ppShare);
  308. return (NERR_Success == ret);
  309. }
  310. BOOL SharePrinter(LPCTSTR pszPrinterName, LPCTSTR pszShareName, LPCTSTR pszPassword)
  311. {
  312. ASSERT(pszPrinterName != NULL);
  313. ASSERT(pszShareName != NULL);
  314. BOOL fResult = FALSE;
  315. if (g_fRunningOnNT)
  316. {
  317. HANDLE hPrinter;
  318. PRINTER_DEFAULTS pd = {0};
  319. pd.DesiredAccess = PRINTER_ALL_ACCESS;
  320. if (OpenPrinter_NT((LPWSTR) pszPrinterName, &hPrinter, &pd))
  321. {
  322. DWORD cbBuffer = 0;
  323. // Get buffer size
  324. if (!GetPrinter_NT(hPrinter, 2, NULL, 0, &cbBuffer) && cbBuffer)
  325. {
  326. PRINTER_INFO_2* pInfo2 = (PRINTER_INFO_2*) LocalAlloc(LPTR, cbBuffer);
  327. if (pInfo2)
  328. {
  329. if (GetPrinter_NT(hPrinter, 2, (LPBYTE) pInfo2, cbBuffer, &cbBuffer))
  330. {
  331. if (pInfo2->Attributes & PRINTER_ATTRIBUTE_SHARED)
  332. {
  333. // Printer is already shared - we're good to go
  334. fResult = TRUE;
  335. }
  336. else
  337. {
  338. // Share printer
  339. pInfo2->Attributes |= PRINTER_ATTRIBUTE_SHARED;
  340. if((!pInfo2->pShareName) || (!pInfo2->pShareName[0]))
  341. {
  342. pInfo2->pShareName = (LPWSTR) pszShareName;
  343. }
  344. fResult = SetPrinter_NT(hPrinter, 2, (LPBYTE) pInfo2, 0);
  345. }
  346. }
  347. LocalFree(pInfo2);
  348. }
  349. }
  350. ClosePrinter_NT(hPrinter);
  351. }
  352. }
  353. else
  354. {
  355. fResult = ShareHelper(pszPrinterName, pszShareName, NETACCESS_FULL, STYPE_PRINTQ, NULL, pszPassword);
  356. if (fResult)
  357. {
  358. Sleep(500); // need to wait for VSERVER to register the changes, same as msprint2
  359. SHChangeNotify(SHCNE_NETSHARE, SHCNF_PRINTER, pszPrinterName, NULL);
  360. }
  361. }
  362. return fResult;
  363. }
  364. BOOL IsPrinterShared(LPCTSTR pszPrinterName)
  365. {
  366. SHARE_INFO* prgShares;
  367. int cShares = EnumLocalShares(&prgShares);
  368. BOOL bShared = IsFolderSharedEx(pszPrinterName, TRUE, TRUE, cShares, prgShares);
  369. NetApiBufferFree(prgShares);
  370. return bShared;
  371. }
  372. BOOL SetSharePassword(LPCTSTR pszShareName, LPCTSTR pszReadOnlyPassword, LPCTSTR pszFullAccessPassword)
  373. {
  374. SHARE_INFO_502* pShare;
  375. BOOL bResult = FALSE;
  376. if (GetShareInfo502(pszShareName, &pShare))
  377. {
  378. ASSERTMSG(NULL == pszReadOnlyPassword, "SetSharePassword can't store roPassword");
  379. if (pszFullAccessPassword == NULL)
  380. pszFullAccessPassword = TEXT("");
  381. pShare->shi502_passwd = (LPTSTR)pszFullAccessPassword;
  382. bResult = SetShareInfo502(pszShareName, pShare);
  383. NetApiBufferFree(pShare);
  384. }
  385. return bResult;
  386. }
  387. BOOL GetSharePassword(LPCTSTR pszShareName, LPTSTR pszReadOnlyPassword, DWORD cchRO, LPTSTR pszFullAccessPassword, DWORD cchFA)
  388. {
  389. SHARE_INFO_502* pShare;
  390. BOOL bResult = GetShareInfo502(pszShareName, &pShare);
  391. if (bResult)
  392. {
  393. ASSERTMSG(NULL==pszReadOnlyPassword, "GetSharePassword can't support roPassword");
  394. if (pszFullAccessPassword != NULL)
  395. StrCpyN(pszFullAccessPassword, pShare->shi502_passwd, cchFA);
  396. NetApiBufferFree(pShare);
  397. }
  398. return bResult;
  399. }