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.

388 lines
11 KiB

  1. #include "shellprv.h"
  2. #include "netview.h"
  3. #include "balmsg.h"
  4. #include "mtpt.h"
  5. #include "ids.h"
  6. #pragma hdrstop
  7. // from mtptarun.cpp
  8. STDAPI_(void) CMtPt_SetWantUI(int iDrive);
  9. //
  10. // Converts an offset to a string to a string pointer.
  11. //
  12. LPCTSTR _Offset2Ptr(LPTSTR pszBase, UINT_PTR offset, UINT * pcb)
  13. {
  14. LPTSTR pszRet;
  15. if (offset == 0)
  16. {
  17. pszRet = NULL;
  18. *pcb = 0;
  19. }
  20. else
  21. {
  22. pszRet = (LPTSTR)((LPBYTE)pszBase + offset);
  23. *pcb = (lstrlen(pszRet) + 1) * sizeof(TCHAR);
  24. }
  25. return pszRet;
  26. }
  27. //
  28. // exported networking APIs from shell32
  29. //
  30. STDAPI_(UINT) SHGetNetResource(HNRES hnres, UINT iItem, LPNETRESOURCE pnresOut, UINT cbMax)
  31. {
  32. UINT iRet = 0; // assume error
  33. LPNRESARRAY panr = (LPNRESARRAY)GlobalLock(hnres);
  34. if (panr)
  35. {
  36. if (iItem==(UINT)-1)
  37. {
  38. iRet = panr->cItems;
  39. }
  40. else if (iItem < panr->cItems)
  41. {
  42. UINT cbProvider, cbRemoteName;
  43. LPCTSTR pszProvider = _Offset2Ptr((LPTSTR)panr, (UINT_PTR)panr->nr[iItem].lpProvider, &cbProvider);
  44. LPCTSTR pszRemoteName = _Offset2Ptr((LPTSTR)panr, (UINT_PTR)panr->nr[iItem].lpRemoteName, &cbRemoteName);
  45. iRet = sizeof(NETRESOURCE) + cbProvider + cbRemoteName;
  46. if (iRet <= cbMax)
  47. {
  48. LPTSTR psz = (LPTSTR)(pnresOut + 1);
  49. *pnresOut = panr->nr[iItem];
  50. if (pnresOut->lpProvider)
  51. {
  52. pnresOut->lpProvider = psz;
  53. lstrcpy(psz, pszProvider);
  54. psz += cbProvider / sizeof(TCHAR);
  55. }
  56. if (pnresOut->lpRemoteName)
  57. {
  58. pnresOut->lpRemoteName = psz;
  59. lstrcpy(psz, pszRemoteName);
  60. }
  61. }
  62. }
  63. GlobalUnlock(hnres);
  64. }
  65. return iRet;
  66. }
  67. STDAPI_(DWORD) SHNetConnectionDialog(HWND hwnd, LPTSTR pszRemoteName, DWORD dwType)
  68. {
  69. CONNECTDLGSTRUCT cds = {0};
  70. NETRESOURCE nr = {0};
  71. cds.cbStructure = sizeof(cds); /* size of this structure in bytes */
  72. cds.hwndOwner = hwnd; /* owner window for the dialog */
  73. cds.lpConnRes = &nr; /* Requested Resource info */
  74. cds.dwFlags = CONNDLG_USE_MRU; /* flags (see below) */
  75. nr.dwType = dwType;
  76. if (pszRemoteName)
  77. {
  78. nr.lpRemoteName = pszRemoteName;
  79. cds.dwFlags = CONNDLG_RO_PATH;
  80. }
  81. DWORD mnr = WNetConnectionDialog1(&cds);
  82. if (mnr == WN_SUCCESS && dwType != RESOURCETYPE_PRINT && cds.dwDevNum != 0)
  83. {
  84. TCHAR szPath[4];
  85. CMountPoint::WantAutorunUI(PathBuildRoot(szPath, cds.dwDevNum - 1 /* 1-based! */));
  86. }
  87. return mnr;
  88. }
  89. typedef struct
  90. {
  91. HWND hwnd;
  92. TCHAR szRemoteName[MAX_PATH];
  93. DWORD dwType;
  94. } SHNETCONNECT;
  95. DWORD CALLBACK _NetConnectThreadProc(void *pv)
  96. {
  97. SHNETCONNECT *pshnc = (SHNETCONNECT *)pv;
  98. HWND hwndDestroy = NULL;
  99. if (!pshnc->hwnd)
  100. {
  101. RECT rc;
  102. LPPOINT ppt;
  103. DWORD pid;
  104. // Wild multimon guess - Since we don't have a parent window,
  105. // we will arbitrarily position ourselves in the same location as
  106. // the foreground window, if the foreground window belongs to our
  107. // process.
  108. HWND hwnd = GetForegroundWindow();
  109. if (hwnd &&
  110. GetWindowThreadProcessId(hwnd, &pid) &&
  111. (pid == GetCurrentProcessId()) &&
  112. GetWindowRect(hwnd, &rc))
  113. {
  114. // Don't use the upper left corner exactly; slide down by
  115. // some fudge factor. We definitely want to get past the
  116. // caption.
  117. rc.top += GetSystemMetrics(SM_CYCAPTION) * 4;
  118. rc.left += GetSystemMetrics(SM_CXVSCROLL) * 4;
  119. ppt = (LPPOINT)&rc;
  120. }
  121. else
  122. {
  123. ppt = NULL;
  124. }
  125. // Create a stub window so the wizard can establish an Alt+Tab icon
  126. hwndDestroy = _CreateStubWindow(ppt, NULL);
  127. pshnc->hwnd = hwndDestroy;
  128. }
  129. SHNetConnectionDialog(pshnc->hwnd, pshnc->szRemoteName[0] ? pshnc->szRemoteName : NULL, pshnc->dwType);
  130. if (hwndDestroy)
  131. DestroyWindow(hwndDestroy);
  132. LocalFree(pshnc);
  133. SHChangeNotifyHandleEvents();
  134. return 0;
  135. }
  136. STDAPI SHStartNetConnectionDialog(HWND hwnd, LPCTSTR pszRemoteName OPTIONAL, DWORD dwType)
  137. {
  138. SHNETCONNECT *pshnc = (SHNETCONNECT *)LocalAlloc(LPTR, sizeof(SHNETCONNECT));
  139. if (pshnc)
  140. {
  141. pshnc->hwnd = hwnd;
  142. pshnc->dwType = dwType;
  143. if (pszRemoteName)
  144. lstrcpyn(pshnc->szRemoteName, pszRemoteName, ARRAYSIZE(pshnc->szRemoteName));
  145. if (!SHCreateThread(_NetConnectThreadProc, pshnc, CTF_PROCESS_REF | CTF_COINIT, NULL))
  146. {
  147. LocalFree((HLOCAL)pshnc);
  148. }
  149. }
  150. return S_OK; // whole thing is async, value here is meaningless
  151. }
  152. #ifdef UNICODE
  153. STDAPI SHStartNetConnectionDialogA(HWND hwnd, LPCSTR pszRemoteName, DWORD dwType)
  154. {
  155. WCHAR wsz[MAX_PATH];
  156. if (pszRemoteName)
  157. {
  158. SHAnsiToUnicode(pszRemoteName, wsz, SIZECHARS(wsz));
  159. pszRemoteName = (LPCSTR)wsz;
  160. }
  161. return SHStartNetConnectionDialog(hwnd, (LPCTSTR)pszRemoteName, dwType);
  162. }
  163. #else
  164. STDAPI SHStartNetConnectionDialogW(HWND hwnd, LPCWSTR pszRemoteName, DWORD dwType)
  165. {
  166. char sz[MAX_PATH];
  167. if (pszRemoteName)
  168. {
  169. SHUnicodeToAnsi(pszRemoteName, sz, SIZECHARS(sz));
  170. pszRemoteName = (LPCWSTR)sz;
  171. }
  172. return SHStartNetConnectionDialog(hwnd, (LPCTSTR)pszRemoteName, dwType);
  173. }
  174. #endif
  175. // These are wrappers around the same WNet APIs, but play with the parameters
  176. // to make it easier to call. They accept full paths rather than just drive letters.
  177. //
  178. DWORD APIENTRY SHWNetDisconnectDialog1 (LPDISCDLGSTRUCT lpConnDlgStruct)
  179. {
  180. TCHAR szLocalName[3];
  181. if (lpConnDlgStruct && lpConnDlgStruct->lpLocalName && lstrlen(lpConnDlgStruct->lpLocalName) > 2)
  182. {
  183. // Kludge allert, don't pass c:\ to API, instead only pass C:
  184. szLocalName[0] = lpConnDlgStruct->lpLocalName[0];
  185. szLocalName[1] = TEXT(':');
  186. szLocalName[2] = 0;
  187. lpConnDlgStruct->lpLocalName = szLocalName;
  188. }
  189. return WNetDisconnectDialog1 (lpConnDlgStruct);
  190. }
  191. DWORD APIENTRY SHWNetGetConnection (LPCTSTR lpLocalName, LPTSTR lpRemoteName, LPDWORD lpnLength)
  192. {
  193. TCHAR szLocalName[3];
  194. if (lpLocalName && lstrlen(lpLocalName) > 2)
  195. {
  196. // Kludge allert, don't pass c:\ to API, instead only pass C:
  197. szLocalName[0] = lpLocalName[0];
  198. szLocalName[1] = TEXT(':');
  199. szLocalName[2] = 0;
  200. lpLocalName = szLocalName;
  201. }
  202. return WNetGetConnection (lpLocalName, lpRemoteName, lpnLength);
  203. }
  204. // exported for netfind.cpp to use
  205. STDAPI SHGetDomainWorkgroupIDList(LPITEMIDLIST *ppidl)
  206. {
  207. *ppidl = NULL;
  208. IShellFolder *psfDesktop;
  209. HRESULT hr = SHGetDesktopFolder(&psfDesktop);
  210. if (SUCCEEDED(hr))
  211. {
  212. TCHAR szName[MAX_PATH];
  213. lstrcpy(szName, TEXT("\\\\"));
  214. if (RegGetValueString(HKEY_LOCAL_MACHINE,
  215. TEXT("SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName"),
  216. TEXT("ComputerName"), szName + 2, sizeof(szName) - 2 * sizeof(TCHAR)))
  217. {
  218. WCHAR wszName[MAX_PATH];
  219. SHTCharToUnicode(szName, wszName, ARRAYSIZE(wszName));
  220. hr = psfDesktop->ParseDisplayName(NULL, NULL, wszName, NULL, ppidl, NULL);
  221. if (SUCCEEDED(hr))
  222. ILRemoveLastID(*ppidl);
  223. }
  224. else
  225. hr = E_FAIL;
  226. psfDesktop->Release();
  227. }
  228. return hr;
  229. }
  230. // SHGetComputerDisplayName - formats and returns the computer name for display.
  231. #define REGSTR_PATH_COMPUTERDESCCACHE REGSTR_PATH_EXPLORER TEXT("\\ComputerDescriptions")
  232. STDAPI_(void) SHCacheComputerDescription(LPCTSTR pszMachineName, LPCTSTR pszDescription)
  233. {
  234. if (pszDescription)
  235. {
  236. DWORD cb = (lstrlen(pszDescription) + 1) * sizeof(*pszDescription);
  237. SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_COMPUTERDESCCACHE, SkipServerSlashes(pszMachineName), REG_SZ, pszDescription, cb);
  238. }
  239. }
  240. STDAPI _GetComputerDescription(LPCTSTR pszMachineName, LPTSTR pszDescription, DWORD cchDescription)
  241. {
  242. SERVER_INFO_101 *psv101 = NULL;
  243. HRESULT hr = ResultFromWin32(NetServerGetInfo((LPWSTR)pszMachineName, 101, (BYTE**)&psv101));
  244. if (SUCCEEDED(hr))
  245. {
  246. if (psv101->sv101_comment && psv101->sv101_comment[0])
  247. {
  248. lstrcpyn(pszDescription, psv101->sv101_comment, cchDescription);
  249. }
  250. else
  251. {
  252. hr = E_FAIL;
  253. }
  254. NetApiBufferFree(psv101);
  255. }
  256. return hr;
  257. }
  258. HRESULT _GetCachedComputerDescription(LPCTSTR pszMachineName, LPTSTR pszDescription, int cchDescription)
  259. {
  260. ULONG cb = cchDescription*sizeof(*pszDescription);
  261. return ResultFromWin32(SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_COMPUTERDESCCACHE, SkipServerSlashes(pszMachineName), NULL, pszDescription, &cb));
  262. }
  263. STDAPI SHGetComputerDisplayNameW(LPCWSTR pszMachineName, DWORD dwFlags, LPWSTR pszDisplay, DWORD cchDisplay)
  264. {
  265. HRESULT hr = E_FAIL;
  266. // map the NULL machine name to the local computer name - so we can cache correctly.
  267. WCHAR szMachineName[CNLEN + 1];
  268. if (!pszMachineName)
  269. {
  270. DWORD cchMachine = ARRAYSIZE(szMachineName);
  271. if (GetComputerName(szMachineName, &cchMachine))
  272. {
  273. pszMachineName = szMachineName;
  274. dwFlags |= SGCDNF_NOCACHEDENTRY;
  275. }
  276. }
  277. // we must have a machine name, so we can perform the look up.
  278. if (pszMachineName)
  279. {
  280. WCHAR szDescription[256];
  281. // can we read the name from teh cache, if not/or the user says they don't want
  282. // the cached name then lets hit the wire and read it.
  283. if (!(dwFlags & SGCDNF_NOCACHEDENTRY))
  284. hr = _GetCachedComputerDescription(pszMachineName, szDescription, ARRAYSIZE(szDescription));
  285. if (FAILED(hr))
  286. {
  287. hr = _GetComputerDescription(pszMachineName, szDescription, ARRAYSIZE(szDescription));
  288. if (FAILED(hr))
  289. {
  290. *szDescription = _TEXT('\0');
  291. }
  292. if (!(dwFlags & SGCDNF_NOCACHEDENTRY))
  293. {
  294. SHCacheComputerDescription(pszMachineName, szDescription); // write through to cache
  295. }
  296. }
  297. // we have a name, so lets format it, if they request description only / or we failed
  298. // above lets just return raw string. otherwise we build a new machine name based
  299. // on the remote name and the description we fetched.
  300. if (SUCCEEDED(hr) && *szDescription)
  301. {
  302. if (dwFlags & SGCDNF_DESCRIPTIONONLY)
  303. {
  304. lstrcpyn(pszDisplay, szDescription, cchDisplay);
  305. hr = S_OK;
  306. }
  307. else
  308. {
  309. hr = SHBuildDisplayMachineName(pszMachineName, szDescription, pszDisplay, cchDisplay);
  310. }
  311. }
  312. else if (!(dwFlags & SGCDNF_DESCRIPTIONONLY))
  313. {
  314. lstrcpyn(pszDisplay, SkipServerSlashes(pszMachineName), cchDisplay);
  315. hr = S_OK;
  316. }
  317. }
  318. return hr;
  319. }