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.

347 lines
8.6 KiB

  1. // utils.cpp : Implementation of helper functions
  2. #include "stdafx.h"
  3. #include <dns.h>
  4. #include <macfile.h>
  5. HRESULT
  6. GetErrorMessageFromModule(
  7. IN DWORD dwError,
  8. IN LPCTSTR lpszDll,
  9. OUT LPTSTR *ppBuffer
  10. )
  11. {
  12. if (0 == dwError || !lpszDll || !*lpszDll || !ppBuffer)
  13. return E_INVALIDARG;
  14. HRESULT hr = S_OK;
  15. HINSTANCE hMsgLib = LoadLibrary(lpszDll);
  16. if (!hMsgLib)
  17. hr = HRESULT_FROM_WIN32(GetLastError());
  18. else
  19. {
  20. DWORD dwRet = ::FormatMessage(
  21. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  22. hMsgLib, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  23. (LPTSTR)ppBuffer, 0, NULL);
  24. if (0 == dwRet)
  25. hr = HRESULT_FROM_WIN32(GetLastError());
  26. FreeLibrary(hMsgLib);
  27. }
  28. return hr;
  29. }
  30. HRESULT
  31. GetErrorMessage(
  32. IN DWORD i_dwError,
  33. OUT CString& cstrErrorMsg
  34. )
  35. {
  36. if (0 == i_dwError)
  37. return E_INVALIDARG;
  38. HRESULT hr = S_OK;
  39. LPTSTR lpBuffer = NULL;
  40. DWORD dwRet = ::FormatMessage(
  41. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  42. NULL, i_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  43. (LPTSTR)&lpBuffer, 0, NULL);
  44. if (0 == dwRet)
  45. {
  46. // if no message is found, GetLastError will return ERROR_MR_MID_NOT_FOUND
  47. hr = HRESULT_FROM_WIN32(GetLastError());
  48. if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr ||
  49. 0x80070000 == (i_dwError & 0xffff0000) ||
  50. 0 == (i_dwError & 0xffff0000) )
  51. {
  52. hr = GetErrorMessageFromModule((i_dwError & 0x0000ffff), _T("netmsg.dll"), &lpBuffer);
  53. if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr)
  54. {
  55. int iError = i_dwError; // convert to a signed integer
  56. if (iError >= AFPERR_MIN && iError < AFPERR_BASE)
  57. {
  58. // use a positive number to search sfmmsg.dll
  59. hr = GetErrorMessageFromModule(-iError, _T("sfmmsg.dll"), &lpBuffer);
  60. }
  61. }
  62. }
  63. }
  64. if (SUCCEEDED(hr))
  65. {
  66. cstrErrorMsg = lpBuffer;
  67. LocalFree(lpBuffer);
  68. }
  69. else
  70. {
  71. // we failed to retrieve the error message from system/netmsg.dll/sfmmsg.dll,
  72. // report the error code directly to user
  73. hr = S_OK;
  74. cstrErrorMsg.Format(_T("0x%x"), i_dwError);
  75. }
  76. return S_OK;
  77. }
  78. void
  79. GetDisplayMessageHelper(
  80. OUT CString& cstrMsg,
  81. IN DWORD dwErr, // error code
  82. IN UINT iStringId, // string resource Id
  83. IN va_list *parglist) // Optional arguments
  84. {
  85. HRESULT hr = S_OK;
  86. CString cstrErrorMsg;
  87. if (dwErr)
  88. hr = GetErrorMessage(dwErr, cstrErrorMsg);
  89. if (SUCCEEDED(hr))
  90. {
  91. if (iStringId == 0)
  92. {
  93. if (dwErr)
  94. {
  95. cstrMsg = cstrErrorMsg;
  96. } else
  97. {
  98. cstrMsg = va_arg(*parglist, LPCTSTR);
  99. }
  100. }
  101. else
  102. {
  103. CString cstrString;
  104. cstrString.LoadString(iStringId);
  105. LPTSTR lpBuffer = NULL;
  106. DWORD dwRet = ::FormatMessage(
  107. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  108. cstrString,
  109. 0, // dwMessageId
  110. 0, // dwLanguageId, ignored
  111. (LPTSTR)&lpBuffer,
  112. 0, // nSize
  113. parglist);
  114. if (dwRet == 0)
  115. {
  116. hr = HRESULT_FROM_WIN32(GetLastError());
  117. }
  118. else
  119. {
  120. cstrMsg = lpBuffer;
  121. if (dwErr)
  122. cstrMsg += cstrErrorMsg;
  123. LocalFree(lpBuffer);
  124. }
  125. }
  126. }
  127. if (FAILED(hr))
  128. {
  129. // Failed to retrieve the proper message, report the failure directly to user
  130. cstrMsg.Format(_T("0x%x"), hr);
  131. }
  132. }
  133. void
  134. GetDisplayMessage(
  135. OUT CString& cstrMsg,
  136. IN DWORD dwErr, // error code
  137. IN UINT iStringId, // string resource Id
  138. ...) // Optional arguments
  139. {
  140. va_list arglist;
  141. va_start(arglist, iStringId);
  142. GetDisplayMessageHelper(cstrMsg, dwErr, iStringId, &arglist);
  143. va_end(arglist);
  144. }
  145. int
  146. DisplayMessageBox(
  147. IN HWND hwndParent,
  148. IN UINT uType, // style of message box
  149. IN DWORD dwErr, // error code
  150. IN UINT iStringId, // string resource Id
  151. ...) // Optional arguments
  152. {
  153. CString cstrCaption;
  154. CString cstrMsg;
  155. cstrCaption.LoadString(IDS_WIZARD_TITLE);
  156. va_list arglist;
  157. va_start(arglist, iStringId);
  158. GetDisplayMessageHelper(cstrMsg, dwErr, iStringId, &arglist);
  159. va_end(arglist);
  160. return ::MessageBox(hwndParent, cstrMsg, cstrCaption, uType);
  161. }
  162. // NOTE: this function only handles limited cases, e.g., no ip address
  163. BOOL IsLocalComputer(IN LPCTSTR lpszComputer)
  164. {
  165. if (!lpszComputer || !*lpszComputer)
  166. return TRUE;
  167. if ( _tcslen(lpszComputer) > 2 && *lpszComputer == _T('\\') && *(lpszComputer + 1) == _T('\\') )
  168. lpszComputer += 2;
  169. BOOL bReturn = FALSE;
  170. DWORD dwErr = 0;
  171. TCHAR szBuffer[DNS_MAX_NAME_BUFFER_LENGTH];
  172. DWORD dwSize = DNS_MAX_NAME_BUFFER_LENGTH;
  173. // 1st: compare against local Netbios computer name
  174. if ( !GetComputerNameEx(ComputerNameNetBIOS, szBuffer, &dwSize) )
  175. {
  176. dwErr = GetLastError();
  177. } else
  178. {
  179. bReturn = (0 == lstrcmpi(szBuffer, lpszComputer));
  180. if (!bReturn)
  181. { // 2nd: compare against local Dns computer name
  182. dwSize = DNS_MAX_NAME_BUFFER_LENGTH;
  183. if (GetComputerNameEx(ComputerNameDnsFullyQualified, szBuffer, &dwSize))
  184. bReturn = (0 == lstrcmpi(szBuffer, lpszComputer));
  185. else
  186. dwErr = GetLastError();
  187. }
  188. }
  189. if (dwErr)
  190. TRACE(_T("IsLocalComputer dwErr = %x\n"), dwErr);
  191. return bReturn;
  192. }
  193. void GetFullPath(
  194. IN LPCTSTR lpszServer,
  195. IN LPCTSTR lpszDir,
  196. OUT CString& cstrPath
  197. )
  198. {
  199. ASSERT(lpszDir && *lpszDir);
  200. if (IsLocalComputer(lpszServer))
  201. {
  202. cstrPath = lpszDir;
  203. } else
  204. {
  205. if (*lpszServer != _T('\\') || *(lpszServer + 1) != _T('\\'))
  206. {
  207. cstrPath = _T("\\\\");
  208. cstrPath += lpszServer;
  209. } else
  210. {
  211. cstrPath = lpszServer;
  212. }
  213. cstrPath += _T("\\");
  214. cstrPath += lpszDir;
  215. int i = cstrPath.Find(_T(':'));
  216. ASSERT(-1 != i);
  217. cstrPath.SetAt(i, _T('$'));
  218. }
  219. }
  220. // Purpose: verify if the specified drive belongs to a list of disk drives on the server
  221. // Return:
  222. // S_OK: yes
  223. // S_FALSE: no
  224. // hr: some error happened
  225. HRESULT
  226. VerifyDriveLetter(
  227. IN LPCTSTR lpszServer,
  228. IN LPCTSTR lpszDrive
  229. )
  230. {
  231. HRESULT hr = S_FALSE;
  232. LPBYTE pBuffer = NULL;
  233. DWORD dwEntriesRead = 0;
  234. DWORD dwTotalEntries = 0;
  235. DWORD dwRet = NetServerDiskEnum(
  236. const_cast<LPTSTR>(lpszServer),
  237. 0,
  238. &pBuffer,
  239. -1,
  240. &dwEntriesRead,
  241. &dwTotalEntries,
  242. NULL);
  243. if (NERR_Success == dwRet)
  244. {
  245. LPTSTR pDrive = (LPTSTR)pBuffer;
  246. for (UINT i=0; i<dwEntriesRead; i++)
  247. {
  248. if (_totupper(*pDrive) == _totupper(*lpszDrive))
  249. {
  250. hr = S_OK;
  251. break;
  252. }
  253. pDrive += 3;
  254. }
  255. NetApiBufferFree(pBuffer);
  256. } else
  257. {
  258. hr = HRESULT_FROM_WIN32(dwRet);
  259. }
  260. return hr;
  261. }
  262. // Purpose: is there a related admin $ share
  263. // Return:
  264. // S_OK: yes
  265. // S_FALSE: no
  266. // hr: some error happened
  267. HRESULT
  268. IsAdminShare(
  269. IN LPCTSTR lpszServer,
  270. IN LPCTSTR lpszDrive
  271. )
  272. {
  273. ASSERT(!IsLocalComputer(lpszServer));
  274. HRESULT hr = S_FALSE;
  275. LPBYTE pBuffer = NULL;
  276. DWORD dwEntriesRead = 0;
  277. DWORD dwTotalEntries = 0;
  278. DWORD dwRet = NetShareEnum(
  279. const_cast<LPTSTR>(lpszServer),
  280. 1,
  281. &pBuffer,
  282. -1,
  283. &dwEntriesRead,
  284. &dwTotalEntries,
  285. NULL);
  286. if (NERR_Success == dwRet)
  287. {
  288. PSHARE_INFO_1 pShareInfo = (PSHARE_INFO_1)pBuffer;
  289. for (UINT i=0; i<dwEntriesRead; i++)
  290. {
  291. if ( (pShareInfo->shi1_type & STYPE_SPECIAL) &&
  292. _tcslen(pShareInfo->shi1_netname) == 2 &&
  293. *(pShareInfo->shi1_netname + 1) == _T('$') &&
  294. _totupper(*(pShareInfo->shi1_netname)) == _totupper(*lpszDrive) )
  295. {
  296. hr = S_OK;
  297. break;
  298. }
  299. pShareInfo++;
  300. }
  301. NetApiBufferFree(pBuffer);
  302. } else
  303. {
  304. hr = HRESULT_FROM_WIN32(dwRet);
  305. }
  306. return hr;
  307. }