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.

395 lines
12 KiB

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