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.

612 lines
16 KiB

  1. #include <fusenetincludes.h>
  2. #include <version.h>
  3. #include "cstrings.h"
  4. HRESULT ConvertVersionStrToULL(LPCWSTR pwzVerStr, ULONGLONG *pullVersion)
  5. {
  6. HRESULT hr = S_OK;
  7. MAKE_ERROR_MACROS_STATIC(hr);
  8. LPCWSTR pwz = NULL;
  9. WORD wVer[4] = {0,0,0,0};
  10. ULONGLONG ullVer = 0;
  11. INT i= 0, iVersion = 0;
  12. BOOL fDot = TRUE;
  13. IF_NULL_EXIT(pwzVerStr, E_INVALIDARG);
  14. IF_NULL_EXIT(pullVersion, E_INVALIDARG);
  15. // Parse the version to ulonglong
  16. pwz = pwzVerStr;
  17. while (*pwz)
  18. {
  19. if (fDot)
  20. {
  21. iVersion=StrToInt(pwz);
  22. wVer[i++] = (WORD) iVersion;
  23. fDot = FALSE;
  24. }
  25. if (*pwz == L'.')
  26. fDot = TRUE;
  27. pwz++;
  28. if (i > 3)
  29. break;
  30. }
  31. for (i = 0; i < 4; i++)
  32. ullVer |= ((ULONGLONG) wVer[i]) << (sizeof(WORD) * 8 * (3-i));
  33. *pullVersion = ullVer;
  34. exit:
  35. return hr;
  36. }
  37. HRESULT FusionCompareString(LPCWSTR pwz1, LPWSTR pwz2, DWORD dwFlags)
  38. {
  39. HRESULT hr = S_OK;
  40. MAKE_ERROR_MACROS_STATIC(hr);
  41. DWORD iCompare = CompareString(LOCALE_USER_DEFAULT, dwFlags,
  42. pwz1, -1, pwz2, -1);
  43. IF_WIN32_FALSE_EXIT(iCompare);
  44. hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
  45. exit:
  46. return hr;
  47. }
  48. VOID MakeRandomString(LPWSTR wzRandom, DWORD cc)
  49. {
  50. static DWORD g_dwCounter;
  51. LPWSTR pwzRandom = wzRandom;
  52. for (DWORD i = 0; i < cc; i++)
  53. {
  54. DWORD dwChar;
  55. DWORD dwRandom;
  56. dwRandom = (GetTickCount() * rand()) + g_dwCounter++;
  57. dwChar = dwRandom % 36; // 10 digits + 26 letters
  58. *pwzRandom++ = (dwChar < 10 ) ?
  59. (WCHAR)(L'0' + dwChar) : (WCHAR)(L'A' + (dwChar - 10));
  60. }
  61. }
  62. HRESULT CreateRandomDir(LPWSTR pwzRootPath, LPWSTR pwzRandomDir, DWORD cchDirLen)
  63. {
  64. HRESULT hr = S_OK;
  65. MAKE_ERROR_MACROS_STATIC(hr);
  66. DWORD dwLastError = 0;
  67. CString sTempDirPath;
  68. BOOL bDone = FALSE;
  69. DWORD dwCount=0;
  70. IF_FAILED_EXIT(::CreateDirectoryHierarchy(NULL, pwzRootPath));
  71. do
  72. {
  73. ::MakeRandomString(pwzRandomDir, cchDirLen);
  74. IF_FAILED_EXIT(sTempDirPath.Assign(pwzRootPath));
  75. IF_FAILED_EXIT(sTempDirPath.Append(pwzRandomDir));
  76. ::SetLastError(0);
  77. ::CreateDirectory(sTempDirPath._pwz, NULL);
  78. dwLastError = ::GetLastError();
  79. switch(dwLastError)
  80. {
  81. case NO_ERROR:
  82. bDone = TRUE;
  83. case ERROR_ALREADY_EXISTS :
  84. break;
  85. default :
  86. _hr = HRESULT_FROM_WIN32(dwLastError);
  87. goto exit;
  88. }
  89. if(bDone)
  90. break;
  91. if(dwCount > 1000)
  92. {
  93. // we tried enough ??
  94. hr = E_FAIL;
  95. goto exit;
  96. }
  97. else
  98. {
  99. dwCount++;
  100. }
  101. } while (1);
  102. exit :
  103. return hr;
  104. }
  105. HRESULT CheckFileExistence(LPCWSTR pwzFile, BOOL *pbExists)
  106. {
  107. HRESULT hr = S_OK;
  108. MAKE_ERROR_MACROS_STATIC(hr);
  109. DWORD dw;
  110. ASSERT(pwzFile && pbExists);
  111. dw = GetFileAttributes(pwzFile);
  112. if (dw == INVALID_FILE_ATTRIBUTES) {
  113. hr = FusionpHresultFromLastError();
  114. if ( (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
  115. (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) )
  116. {
  117. *pbExists = FALSE;
  118. hr = S_OK;
  119. }
  120. goto exit;
  121. }
  122. *pbExists = TRUE;
  123. exit:
  124. return hr;
  125. }
  126. /////////////////////////////////////////////////////////////////////////
  127. // CreateDirectoryHierarchy
  128. /////////////////////////////////////////////////////////////////////////
  129. HRESULT CreateDirectoryHierarchy(LPWSTR pwzRootDir, LPWSTR pwzFilePath)
  130. {
  131. HRESULT hr = S_OK;
  132. MAKE_ERROR_MACROS_STATIC(hr);
  133. LPWSTR pwzPath, pwzEnd;
  134. CString sCombinedPath;
  135. IF_FALSE_EXIT(pwzRootDir || pwzFilePath, E_INVALIDARG);
  136. if (pwzRootDir)
  137. IF_FAILED_EXIT(sCombinedPath.Assign(pwzRootDir));
  138. if (pwzFilePath)
  139. IF_FAILED_EXIT(sCombinedPath.Append(pwzFilePath));
  140. pwzPath = sCombinedPath._pwz;
  141. pwzEnd = pwzPath + sizeof("C:\\");
  142. while (pwzEnd = StrChr(pwzEnd, L'\\'))
  143. {
  144. BOOL bExists;
  145. *pwzEnd = L'\0';
  146. IF_FAILED_EXIT(CheckFileExistence(pwzPath, &bExists));
  147. if (!bExists)
  148. {
  149. if(!CreateDirectory(pwzPath, NULL))
  150. {
  151. hr = FusionpHresultFromLastError();
  152. goto exit;
  153. }
  154. }
  155. *(pwzEnd++) = L'\\';
  156. }
  157. exit:
  158. return hr;
  159. }
  160. HRESULT RemoveDirectoryAndChildren(LPWSTR szDir)
  161. {
  162. HRESULT hr = S_OK;
  163. MAKE_ERROR_MACROS_STATIC(hr);
  164. HANDLE hf = INVALID_HANDLE_VALUE;
  165. WIN32_FIND_DATA fd;
  166. CString sBuf;
  167. DWORD dwError = 0;
  168. IF_NULL_EXIT(szDir && lstrlenW(szDir), E_INVALIDARG);
  169. IF_FAILED_EXIT(sBuf.Assign(szDir));
  170. // Cannot delete root. Path must have greater length than "x:\"
  171. if (lstrlenW(sBuf._pwz) < 4) {
  172. // ASSERT(0);
  173. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  174. goto exit;
  175. }
  176. if (RemoveDirectory(sBuf._pwz)) {
  177. goto exit;
  178. }
  179. // ha! we have a case where the directory is probbaly not empty
  180. IF_FAILED_EXIT(sBuf.Append(TEXT("\\*")));
  181. if ((hf = FindFirstFile(sBuf._pwz, &fd)) == INVALID_HANDLE_VALUE) {
  182. dwError = GetLastError();
  183. if(dwError == ERROR_PATH_NOT_FOUND)
  184. hr = S_FALSE;
  185. else
  186. hr = HRESULT_FROM_WIN32(dwError);
  187. goto exit;
  188. }
  189. do {
  190. IF_FAILED_EXIT(FusionCompareString(fd.cFileName, TEXT("."), 0));
  191. if(hr == S_OK)
  192. continue;
  193. IF_FAILED_EXIT(FusionCompareString(fd.cFileName, TEXT(".."), 0));
  194. if(hr == S_OK)
  195. continue;
  196. IF_FAILED_EXIT(sBuf.Assign(szDir));
  197. IF_FAILED_EXIT(sBuf.Append(TEXT("\\")));
  198. IF_FAILED_EXIT(sBuf.Append(fd.cFileName));
  199. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  200. SetFileAttributes(sBuf._pwz,
  201. FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_NORMAL);
  202. IF_FAILED_EXIT(RemoveDirectoryAndChildren(sBuf._pwz));
  203. } else {
  204. SetFileAttributes(sBuf._pwz, FILE_ATTRIBUTE_NORMAL);
  205. IF_WIN32_FALSE_EXIT(DeleteFile(sBuf._pwz));
  206. }
  207. } while (FindNextFile(hf, &fd));
  208. dwError = GetLastError();
  209. if (dwError != ERROR_NO_MORE_FILES) {
  210. hr = HRESULT_FROM_WIN32(dwError);
  211. goto exit;
  212. }
  213. if (hf != INVALID_HANDLE_VALUE) {
  214. FindClose(hf);
  215. hf = INVALID_HANDLE_VALUE;
  216. }
  217. // here if all subdirs/children removed
  218. /// re-attempt to remove the main dir
  219. if (!RemoveDirectory(szDir)) {
  220. dwError = GetLastError();
  221. hr = HRESULT_FROM_WIN32(dwError);
  222. goto exit;
  223. }
  224. exit:
  225. if (hf != INVALID_HANDLE_VALUE)
  226. FindClose(hf);
  227. return hr;
  228. }
  229. HRESULT FusionpHresultFromLastError()
  230. {
  231. HRESULT hr = S_OK;
  232. DWORD dwLastError = GetLastError();
  233. if (dwLastError != NO_ERROR)
  234. {
  235. hr = HRESULT_FROM_WIN32(dwLastError);
  236. }
  237. else
  238. {
  239. hr = E_FAIL;
  240. }
  241. return hr;
  242. }
  243. // ---------------------------------------------------------------------------
  244. // IsKnownAssembly
  245. // ---------------------------------------------------------------------------
  246. HRESULT IsKnownAssembly(IAssemblyIdentity *pId, DWORD dwFlags)
  247. {
  248. HRESULT hr = S_FALSE;
  249. MAKE_ERROR_MACROS_STATIC(hr);
  250. LPWSTR pwz = NULL;
  251. DWORD cc = 0;
  252. CString sPublicKeyToken;
  253. // URT system assemblies; these are not downloaded or installed.
  254. LPWSTR wzSystemTokens[] = { L"b03f5f7f11d50a3a", L"b77a5c561934e089" };
  255. // Avalon assemblies - can be installed to gac.
  256. LPWSTR wzAvalonTokens[] = { L"a29c01bbd4e39ac5" };
  257. // Get the public key token in string form.
  258. if (pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwz, &cc) != S_OK)
  259. goto exit;
  260. sPublicKeyToken.TakeOwnership(pwz);
  261. // Check for system assembly.
  262. if (dwFlags == KNOWN_SYSTEM_ASSEMBLY)
  263. {
  264. for (int i = 0; i < 2; i++)
  265. {
  266. IF_FAILED_EXIT(FusionCompareString(wzSystemTokens[i], sPublicKeyToken._pwz, NORM_IGNORECASE));
  267. if(hr == S_OK)
  268. break;
  269. }
  270. }
  271. // check for Avalon assembly.
  272. else if (dwFlags == KNOWN_TRUSTED_ASSEMBLY)
  273. {
  274. IF_FAILED_EXIT(FusionCompareString(wzAvalonTokens[0], sPublicKeyToken._pwz, NORM_IGNORECASE));
  275. }
  276. exit:
  277. return hr;
  278. }
  279. BOOL DoHeapValidate()
  280. {
  281. HANDLE h = GetProcessHeap();
  282. return HeapValidate(h, 0, NULL);
  283. }
  284. //=--------------------------------------------------------------------------=
  285. // EnsureDebuggerPresent
  286. //=--------------------------------------------------------------------------=
  287. // Ensures that a debugger is present. If one isn't present, this will attempt
  288. // to attach one. If no debugger is installed on the machine, this will
  289. // display a message and return FALSE.
  290. //
  291. BOOL EnsureDebuggerPresent()
  292. {
  293. BOOL fRet = TRUE;
  294. HRESULT hr = S_OK;
  295. MAKE_ERROR_MACROS_STATIC(hr);
  296. HKEY hKey = NULL;
  297. typedef BOOL (WINAPI* ISDEBUGGERPRESENT)();
  298. static BOOL _fStartedDebugger = FALSE;
  299. static ISDEBUGGERPRESENT _IsDebuggerPresent = NULL;
  300. // If we've already done the work to start the debugger, we're fine
  301. //
  302. if (_fStartedDebugger)
  303. {
  304. fRet = TRUE;
  305. goto exit;
  306. }
  307. // First, if we don't have an IsDebuggerPresent API, look for one.
  308. //
  309. if (!_IsDebuggerPresent)
  310. {
  311. HMODULE hKernel = NULL;
  312. hKernel = GetModuleHandle (L"Kernel32.dll");
  313. if (!hKernel)
  314. {
  315. MessageBox(NULL, L"Unable to attach to debugger because we could not find Kernel32.dll", L"VsAssert", MB_OK | MB_ICONSTOP);
  316. fRet = FALSE;
  317. goto exit;
  318. }
  319. _IsDebuggerPresent = (ISDEBUGGERPRESENT)GetProcAddress(hKernel, "IsDebuggerPresent");
  320. if (!_IsDebuggerPresent)
  321. {
  322. MessageBox(NULL, L"Unable to attach to debugger because we could not find a suitable IsDebuggerPresent API", L"VsAssert", MB_OK | MB_ICONSTOP);
  323. fRet = FALSE;
  324. goto exit;
  325. }
  326. }
  327. // Now find out if the debugger is indeed present.
  328. //
  329. if (_IsDebuggerPresent())
  330. {
  331. _fStartedDebugger = TRUE;
  332. }
  333. else
  334. {
  335. // The debugger has not been started yet. Do this here.
  336. //
  337. BOOL fJIT = FALSE;
  338. //
  339. // Magic! Location of the JIT debugger info...
  340. //
  341. WCHAR *wzRegKey = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
  342. LONG lRetVal;
  343. lRetVal = RegOpenKeyEx(
  344. HKEY_LOCAL_MACHINE,
  345. wzRegKey,
  346. 0,
  347. KEY_READ,
  348. &hKey);
  349. CString sCommandLine;
  350. DWORD dwSize = MAX_PATH;
  351. BOOL fResult;
  352. PROCESS_INFORMATION pi;
  353. IF_FAILED_EXIT(sCommandLine.ResizeBuffer(dwSize+1));
  354. if (lRetVal == ERROR_SUCCESS)
  355. {
  356. DWORD dwType;
  357. lRetVal = RegQueryValueEx(
  358. hKey,
  359. L"Debugger",
  360. 0,
  361. &dwType,
  362. (BYTE *)sCommandLine._pwz,
  363. &dwSize);
  364. RegCloseKey(hKey);
  365. hKey = NULL; // reset the value after closing....
  366. if (lRetVal == ERROR_SUCCESS)
  367. {
  368. fJIT = TRUE;
  369. }
  370. }
  371. else
  372. {
  373. //
  374. // Try WIN.INI
  375. GetProfileString(L"AeDebug", L"Debugger", L"", sCommandLine._pwz,
  376. dwSize);
  377. if (lstrlen(sCommandLine._pwz) != 0)
  378. {
  379. fJIT = TRUE;
  380. }
  381. }
  382. if (!fJIT)
  383. {
  384. MessageBox(NULL, L"Unable to attach to debugger because we could not find a debugger on this machine.", L"VsAssert", MB_OK | MB_ICONSTOP);
  385. fRet = FALSE;
  386. goto exit;
  387. }
  388. HANDLE hEvent;
  389. //
  390. // Now that we have the JIT debugger, try to start it.
  391. // The JIT needs a process ID (ours), and an event.
  392. //
  393. SECURITY_ATTRIBUTES sa;
  394. memset(&sa, 0 , sizeof(sa));
  395. sa.nLength = sizeof(sa);
  396. sa.bInheritHandle = TRUE;
  397. hEvent = CreateEvent(&sa, TRUE, FALSE, NULL);
  398. if (hEvent != NULL)
  399. {
  400. CString sCommand;
  401. DWORD ccSize = 2 * MAX_PATH + 1 ;
  402. BOOL fResult;
  403. PROCESS_INFORMATION pi;
  404. IF_FAILED_EXIT(sCommand.ResizeBuffer(ccSize));
  405. wnsprintf(sCommand._pwz, ccSize-1, sCommandLine._pwz, GetCurrentProcessId(), hEvent);
  406. sCommand._pwz[ccSize-1] = L'\0';
  407. __try
  408. {
  409. STARTUPINFO si;
  410. memset(&si, 0, sizeof(STARTUPINFO));
  411. si.cb = sizeof(STARTUPINFO);
  412. fResult = CreateProcess(
  413. NULL,
  414. sCommand._pwz,
  415. NULL,
  416. NULL,
  417. TRUE,
  418. 0,
  419. NULL,
  420. NULL,
  421. &si,
  422. &pi);
  423. }
  424. __except (EXCEPTION_EXECUTE_HANDLER)
  425. {
  426. fResult = FALSE;
  427. }
  428. if (fResult)
  429. {
  430. CloseHandle(pi.hProcess);
  431. CloseHandle(pi.hThread);
  432. _fStartedDebugger = TRUE;
  433. WaitForSingleObject(hEvent, INFINITE);
  434. CloseHandle(hEvent);
  435. }
  436. else
  437. {
  438. CString sPoof;
  439. DWORD ccSize = 2 * MAX_PATH + 100 ;
  440. IF_FAILED_EXIT(sPoof.ResizeBuffer(ccSize));
  441. wnsprintf(sPoof._pwz, sPoof._cc, L"Unable to invoke the debugger. The invocation command we used was:\r\n\r\n%s", sCommand._pwz);
  442. sPoof._pwz[ccSize-1] = L'\0';
  443. MessageBox(NULL, sPoof._pwz, L"VsAssert", MB_OK | MB_ICONSTOP);
  444. fRet = FALSE;
  445. goto exit;
  446. }
  447. }
  448. }
  449. exit :
  450. if(hKey)
  451. RegCloseKey(hKey);
  452. return fRet;
  453. }
  454. // shlwapi either path- or url-combine
  455. HRESULT DoPathCombine(CString& sDest, LPWSTR pwzSource)
  456. {
  457. HRESULT hr = S_OK;
  458. MAKE_ERROR_MACROS_STATIC(hr);
  459. LPWSTR pwzDir = NULL, pwzTemp = NULL;
  460. DWORD ccSource = 0, ccCombined = 0, dwFlags = 0;
  461. ccSource = lstrlen(pwzSource) + 1;
  462. ccCombined = sDest._cc + ccSource;
  463. IF_FAILED_EXIT(sDest.ResizeBuffer(ccCombined));
  464. pwzDir = WSTRDupDynamic(sDest._pwz);
  465. pwzTemp = ::PathCombine(sDest._pwz, pwzDir, pwzSource);
  466. IF_NULL_EXIT(pwzTemp, E_FAIL);
  467. sDest._cc = lstrlen(sDest._pwz) + 1;
  468. exit:
  469. SAFEDELETEARRAY(pwzDir);
  470. return S_OK;
  471. }