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.

590 lines
18 KiB

  1. #include "pch.h"
  2. #include "iedetect.h"
  3. #define VALID_SIGNATURE 0x5c3f3f5c // string "\??\"
  4. #define REMOVE_QUOTES 0x01
  5. #define IGNORE_QUOTES 0x02
  6. CONST CHAR g_cszWininit[] = "wininit.ini";
  7. CONST CHAR g_cszRenameSec[] = "Rename";
  8. CONST CHAR g_cszPFROKey[] = REGSTR_PATH_CURRENT_CONTROL_SET "\\SESSION MANAGER";
  9. CONST CHAR g_cszPFRO[] = "PendingFileRenameOperations";
  10. DWORD CheckFileEx(LPSTR szDir, DETECT_FILES Detect_Files);
  11. DWORD GetStringField(LPSTR szStr, UINT uField, char cDelimiter, LPSTR szBuf, UINT cBufSize)
  12. {
  13. LPSTR pszBegin = szStr;
  14. LPSTR pszEnd;
  15. UINT i = 0;
  16. DWORD dwToCopy;
  17. if(cBufSize == 0)
  18. return 0;
  19. szBuf[0] = 0;
  20. if(szStr == NULL)
  21. return 0;
  22. while(*pszBegin != 0 && i < uField)
  23. {
  24. pszBegin = FindChar(pszBegin, cDelimiter);
  25. if(*pszBegin != 0)
  26. pszBegin++;
  27. i++;
  28. }
  29. // we reached end of string, no field
  30. if(*pszBegin == 0)
  31. {
  32. return 0;
  33. }
  34. pszEnd = FindChar(pszBegin, cDelimiter);
  35. while(pszBegin <= pszEnd && *pszBegin == ' ')
  36. pszBegin++;
  37. while(pszEnd > pszBegin && *(pszEnd - 1) == ' ')
  38. pszEnd--;
  39. if(pszEnd > (pszBegin + 1) && *pszBegin == '"' && *(pszEnd-1) == '"')
  40. {
  41. pszBegin++;
  42. pszEnd--;
  43. }
  44. dwToCopy = (DWORD)(pszEnd - pszBegin + 1);
  45. if(dwToCopy > cBufSize)
  46. dwToCopy = cBufSize;
  47. lstrcpynA(szBuf, pszBegin, dwToCopy);
  48. return dwToCopy - 1;
  49. }
  50. DWORD GetIntField(LPSTR szStr, char cDelimiter, UINT uField, DWORD dwDefault)
  51. {
  52. char szNumBuf[16];
  53. if(GetStringField(szStr, uField, cDelimiter, szNumBuf, sizeof(szNumBuf)) == 0)
  54. return dwDefault;
  55. else
  56. return AtoL(szNumBuf);
  57. }
  58. int CompareLocales(LPCSTR pcszLoc1, LPCSTR pcszLoc2)
  59. {
  60. int ret;
  61. if(pcszLoc1[0] == '*' || pcszLoc2[0] == '*')
  62. ret = 0;
  63. else
  64. ret = lstrcmpi(pcszLoc1, pcszLoc2);
  65. return ret;
  66. }
  67. void ConvertVersionStrToDwords(LPSTR pszVer, char cDelimiter, LPDWORD pdwVer, LPDWORD pdwBuild)
  68. {
  69. DWORD dwTemp1,dwTemp2;
  70. dwTemp1 = GetIntField(pszVer, cDelimiter, 0, 0);
  71. dwTemp2 = GetIntField(pszVer, cDelimiter, 1, 0);
  72. *pdwVer = (dwTemp1 << 16) + dwTemp2;
  73. dwTemp1 = GetIntField(pszVer, cDelimiter, 2, 0);
  74. dwTemp2 = GetIntField(pszVer, cDelimiter, 3, 0);
  75. *pdwBuild = (dwTemp1 << 16) + dwTemp2;
  76. }
  77. LPSTR FindChar(LPSTR pszStr, char ch)
  78. {
  79. while( *pszStr != 0 && *pszStr != ch )
  80. pszStr++;
  81. return pszStr;
  82. }
  83. DWORD CompareVersions(DWORD dwAskVer, DWORD dwAskBuild, DWORD dwInstalledVer, DWORD dwInstalledBuild)
  84. {
  85. DWORD dwRet = DET_NOTINSTALLED;
  86. if((dwInstalledVer == dwAskVer) && (dwInstalledBuild == dwAskBuild))
  87. {
  88. dwRet = DET_INSTALLED;
  89. }
  90. else if( (dwInstalledVer > dwAskVer) ||
  91. ((dwInstalledVer == dwAskVer) && (dwInstalledBuild > dwAskBuild)) )
  92. {
  93. dwRet = DET_NEWVERSIONINSTALLED;
  94. }
  95. else if( (dwInstalledVer < dwAskVer) ||
  96. ((dwInstalledVer == dwAskVer) && (dwInstalledBuild < dwAskBuild)) )
  97. {
  98. dwRet = DET_OLDVERSIONINSTALLED;
  99. }
  100. return dwRet;
  101. }
  102. BOOL FRunningOnNT(void)
  103. {
  104. static BOOL fIsNT = 2 ;
  105. OSVERSIONINFO VerInfo;
  106. // If we have calculated this before just pass that back.
  107. // else find it now.
  108. //
  109. if (fIsNT == 2)
  110. {
  111. VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  112. GetVersionEx(&VerInfo);
  113. // Note: We don't check for Win32S on Win 3.1 here -- that should
  114. // have been a blocking check earlier in fn CheckWinVer().
  115. // Also, we don't check for failure on the above call as it
  116. // should succeed if we are on NT 4.0 or Win 9X!
  117. //
  118. fIsNT = (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  119. }
  120. return fIsNT;
  121. }
  122. BOOL GetVersionFromGuid(LPSTR pszGuid, LPDWORD pdwVer, LPDWORD pdwBuild)
  123. {
  124. HKEY hKey;
  125. char szValue[MAX_PATH];
  126. DWORD dwValue = 0;
  127. DWORD dwSize;
  128. BOOL bVersion = FALSE;
  129. if (pdwVer && pdwBuild)
  130. {
  131. *pdwVer = 0;
  132. *pdwBuild = 0;
  133. lstrcpy(szValue, COMPONENT_KEY);
  134. AddPath(szValue, pszGuid);
  135. if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, szValue, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  136. {
  137. dwSize = sizeof(dwValue);
  138. if(RegQueryValueEx(hKey, ISINSTALLED_KEY, 0, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS)
  139. {
  140. if (dwValue != 0)
  141. {
  142. dwSize = sizeof(szValue);
  143. if(RegQueryValueEx(hKey, VERSION_KEY, 0, NULL, (LPBYTE)szValue, &dwSize) == ERROR_SUCCESS)
  144. {
  145. ConvertVersionStrToDwords(szValue, ',', pdwVer, pdwBuild);
  146. bVersion = TRUE;
  147. }
  148. }
  149. }
  150. RegCloseKey(hKey);
  151. }
  152. }
  153. return bVersion;
  154. }
  155. BOOL CompareLocal(LPCSTR pszGuid, LPCSTR pszLocal)
  156. {
  157. HKEY hKey;
  158. char szValue[MAX_PATH];
  159. DWORD dwSize;
  160. BOOL bLocal = FALSE;
  161. if (lstrcmpi(pszLocal, "*") == 0)
  162. {
  163. bLocal = TRUE;
  164. }
  165. else
  166. {
  167. lstrcpy(szValue, COMPONENT_KEY);
  168. AddPath(szValue, pszGuid);
  169. if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, szValue, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  170. {
  171. dwSize = sizeof(szValue);
  172. if(RegQueryValueEx(hKey, LOCALE_KEY, 0, NULL, (LPBYTE)szValue, &dwSize) == ERROR_SUCCESS)
  173. {
  174. bLocal = (lstrcmpi(szValue, pszLocal) == 0);
  175. }
  176. RegCloseKey(hKey);
  177. }
  178. }
  179. return bLocal;
  180. }
  181. PSTR GetNextField(PSTR *ppszData, PCSTR pcszDeLims, DWORD dwFlags)
  182. // If (dwFlags & IGNORE_QUOTES) is TRUE, then look for any char in pcszDeLims in *ppszData. If found,
  183. // replace it with the '\0' char and set *ppszData to point to the beginning of the next field and return
  184. // pointer to current field.
  185. //
  186. // If (dwFlags & IGNORE_QUOTES) is FALSE, then look for any char in pcszDeLims outside of balanced quoted sub-strings
  187. // in *ppszData. If found, replace it with the '\0' char and set *ppszData to point to the beginning of
  188. // the next field and return pointer to current field.
  189. //
  190. // If (dwFlags & REMOVE_QUOTES) is TRUE, then remove the surrounding quotes and replace two consecutive quotes by one.
  191. //
  192. // NOTE: If IGNORE_QUOTES and REMOVE_QUOTES are both specified, then IGNORE_QUOTES takes precedence over REMOVE_QUOTES.
  193. //
  194. // If you just want to remove the quotes from a string, call this function as
  195. // GetNextField(&pszData, "\"" or "'" or "", REMOVE_QUOTES).
  196. //
  197. // If you call this function as GetNextField(&pszData, "\"" or "'" or "", 0), you will get back the
  198. // entire pszData as the field.
  199. //
  200. {
  201. PSTR pszRetPtr, pszPtr;
  202. BOOL fWithinQuotes = FALSE, fRemoveQuote;
  203. CHAR chQuote;
  204. if (ppszData == NULL || *ppszData == NULL || **ppszData == '\0')
  205. return NULL;
  206. for (pszRetPtr = pszPtr = *ppszData; *pszPtr; pszPtr = CharNext(pszPtr))
  207. {
  208. if (!(dwFlags & IGNORE_QUOTES) && (*pszPtr == '"' || *pszPtr == '\''))
  209. {
  210. fRemoveQuote = FALSE;
  211. if (*pszPtr == *(pszPtr + 1)) // two consecutive quotes become one
  212. {
  213. pszPtr++;
  214. if (dwFlags & REMOVE_QUOTES)
  215. fRemoveQuote = TRUE;
  216. else
  217. {
  218. // if pcszDeLims is '"' or '\'', then *pszPtr == pcszDeLims would
  219. // be TRUE and we would break out of the loop against the design specs;
  220. // to prevent this just continue
  221. continue;
  222. }
  223. }
  224. else if (!fWithinQuotes)
  225. {
  226. fWithinQuotes = TRUE;
  227. chQuote = *pszPtr; // save the quote char
  228. fRemoveQuote = dwFlags & REMOVE_QUOTES;
  229. }
  230. else
  231. {
  232. if (*pszPtr == chQuote) // match the correct quote char
  233. {
  234. fWithinQuotes = FALSE;
  235. fRemoveQuote = dwFlags & REMOVE_QUOTES;
  236. }
  237. }
  238. if (fRemoveQuote)
  239. {
  240. // shift the entire string one char to the left to get rid of the quote char
  241. MoveMemory(pszPtr, pszPtr + 1, lstrlen(pszPtr));
  242. }
  243. }
  244. // BUGBUG: Is type casting pszPtr to UNALIGNED necessary? -- copied it from ANSIStrChr
  245. // check if pszPtr is pointing to one of the chars in pcszDeLims
  246. if (!fWithinQuotes &&
  247. ANSIStrChr(pcszDeLims, (WORD) (IsDBCSLeadByte(*pszPtr) ? *((UNALIGNED WORD *) pszPtr) : *pszPtr)) != NULL)
  248. break;
  249. }
  250. // NOTE: if fWithinQuotes is TRUE here, then we have an unbalanced quoted string; but we don't care!
  251. // the entire string after the beginning quote becomes the field
  252. if (*pszPtr) // pszPtr is pointing to a char in pcszDeLims
  253. {
  254. *ppszData = CharNext(pszPtr); // save the pointer to the beginning of next field in *ppszData
  255. *pszPtr = '\0'; // replace the DeLim char with the '\0' char
  256. }
  257. else
  258. *ppszData = pszPtr; // we have reached the end of the string; next call to this function
  259. // would return NULL
  260. return pszRetPtr;
  261. }
  262. PSTR GetDataFromWininitOrPFRO(PCSTR pcszWininit, HKEY hkPFROKey, PDWORD pdwLen)
  263. {
  264. PSTR pszData, pszPtr;
  265. *pdwLen = 0;
  266. if (!FRunningOnNT())
  267. {
  268. HANDLE hFile;
  269. WIN32_FIND_DATA FileData;
  270. // find the size of pcszWininit
  271. if ((hFile = FindFirstFile(pcszWininit, &FileData)) != INVALID_HANDLE_VALUE)
  272. {
  273. *pdwLen = FileData.nFileSizeLow;
  274. FindClose(hFile);
  275. }
  276. if (*pdwLen == 0 || (pszData = (PSTR) LocalAlloc(LPTR, *pdwLen)) == NULL)
  277. return NULL;
  278. GetPrivateProfileSection(g_cszRenameSec, pszData, *pdwLen, pcszWininit);
  279. // replace the ='s by \0's
  280. // BUGBUG: assuming that all the lines in wininit.ini have the correct format, i.e., to=from
  281. for (pszPtr = pszData; *pszPtr; pszPtr += lstrlen(pszPtr) + 1)
  282. GetNextField(&pszPtr, "=", IGNORE_QUOTES);
  283. }
  284. else
  285. {
  286. if (hkPFROKey == NULL)
  287. return NULL;
  288. // get the length of value data
  289. RegQueryValueEx(hkPFROKey, g_cszPFRO, NULL, NULL, NULL, pdwLen);
  290. if (*pdwLen == 0 || (pszData = (PSTR) LocalAlloc(LPTR, *pdwLen)) == NULL)
  291. return NULL;
  292. // get the data
  293. RegQueryValueEx(hkPFROKey, g_cszPFRO, NULL, NULL, (PBYTE) pszData, pdwLen);
  294. }
  295. return pszData;
  296. }
  297. VOID ReadFromWininitOrPFRO(PCSTR pcszKey, PSTR pszValue)
  298. {
  299. CHAR szShortName[MAX_PATH];
  300. CHAR szWininit[MAX_PATH];
  301. PSTR pszData, pszLine, pszFrom, pszTo;
  302. DWORD dwLen;
  303. HKEY hkPFROKey = NULL;
  304. if (!FRunningOnNT())
  305. {
  306. GetWindowsDirectory(szWininit, sizeof(szWininit));
  307. AddPath(szWininit, g_cszWininit);
  308. }
  309. else
  310. RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_cszPFROKey, 0, KEY_READ, &hkPFROKey);
  311. // return empty string if pcszKey could not be found
  312. *pszValue = '\0';
  313. if ((pszData = GetDataFromWininitOrPFRO(szWininit, hkPFROKey, &dwLen)) == NULL)
  314. {
  315. if (hkPFROKey != NULL)
  316. RegCloseKey(hkPFROKey);
  317. return;
  318. }
  319. if (!FRunningOnNT())
  320. {
  321. GetShortPathName(pcszKey, szShortName, sizeof(szShortName));
  322. pcszKey = szShortName;
  323. }
  324. pszLine = pszData;
  325. while (*pszLine)
  326. {
  327. // NOTE: On Win95, the format is (To, From) but on NT4.0, the format is (From, To)
  328. if (!FRunningOnNT())
  329. {
  330. // format of GetPrivateProfileSection data is:
  331. //
  332. // to1=from1\0 ; from1 is the Value and to1 is the Key
  333. // to2=from2\0
  334. // NUL=del1\0 ; del1 is the Key
  335. // NUL=del2\0
  336. // .
  337. // .
  338. // .
  339. // to<n>=from<n>\0\0
  340. pszTo = pszLine; // key
  341. pszFrom = pszLine + lstrlen(pszLine) + 1;
  342. pszLine = pszFrom + lstrlen(pszFrom) + 1; // point to the next line
  343. }
  344. else
  345. {
  346. // format of the value data for PFRO value name is:
  347. //
  348. // from1\0to1\0 ; from1 is the Value and to1 is the Key
  349. // from2\0to2\0
  350. // del1\0\0 ; del1 is the Key
  351. // del2\0\0
  352. // .
  353. // .
  354. // .
  355. // from<n>\0to<n>\0\0
  356. pszFrom = pszLine;
  357. pszTo = pszLine + lstrlen(pszLine) + 1; // key
  358. pszLine = pszTo + lstrlen(pszTo) + 1; // point to the next line
  359. // skip over "\??\"
  360. if (*pszFrom == '\\') // '\\' is not a Leading DBCS byte
  361. {
  362. if (*((PDWORD) pszFrom) == VALID_SIGNATURE)
  363. pszFrom += 4;
  364. else
  365. continue;
  366. }
  367. if (*pszTo == '!') // '!' is neither a Leading nor a Trailing DBCS byte
  368. pszTo++;
  369. if (*pszTo == '\\')
  370. {
  371. if (*((PDWORD) pszTo) == VALID_SIGNATURE)
  372. pszTo += 4;
  373. else
  374. continue;
  375. }
  376. }
  377. if (lstrcmpi(pcszKey, pszTo) == 0) // if there is more than one entry, return the last one
  378. lstrcpy(pszValue, pszFrom);
  379. }
  380. LocalFree(pszData);
  381. if (hkPFROKey != NULL)
  382. RegCloseKey(hkPFROKey);
  383. }
  384. DWORD CheckFile(DETECT_FILES Detect_Files)
  385. {
  386. char szFile[MAX_PATH] = { 0 };
  387. DWORD dwRet = DET_NOTINSTALLED;
  388. DWORD dwRetLast = DET_NOTINSTALLED;
  389. int i =0;
  390. while (Detect_Files.cPath[i])
  391. {
  392. switch (Detect_Files.cPath[i])
  393. {
  394. case 'S':
  395. case 's':
  396. GetSystemDirectory( szFile, sizeof(szFile) );
  397. break;
  398. case 'W':
  399. case 'w':
  400. GetWindowsDirectory( szFile, sizeof(szFile) );
  401. break;
  402. // Windows command folder
  403. case 'C':
  404. case 'c':
  405. GetWindowsDirectory( szFile, sizeof(szFile) );
  406. AddPath(szFile, "Command");
  407. break;
  408. default:
  409. *szFile = '\0';
  410. }
  411. if (*szFile)
  412. {
  413. dwRet = CheckFileEx(szFile, Detect_Files);
  414. switch (dwRet)
  415. {
  416. case DET_NOTINSTALLED:
  417. break;
  418. case DET_OLDVERSIONINSTALLED:
  419. if (dwRetLast == DET_NOTINSTALLED)
  420. dwRetLast = dwRet;
  421. break;
  422. case DET_INSTALLED:
  423. if ((dwRetLast == DET_NOTINSTALLED) ||
  424. (dwRetLast == DET_OLDVERSIONINSTALLED))
  425. dwRetLast = dwRet;
  426. break;
  427. case DET_NEWVERSIONINSTALLED:
  428. if ((dwRetLast == DET_NOTINSTALLED) ||
  429. (dwRetLast == DET_OLDVERSIONINSTALLED) ||
  430. (dwRetLast == DET_INSTALLED))
  431. dwRetLast = dwRet;
  432. break;
  433. }
  434. }
  435. // go to the next directory letter.
  436. while ((Detect_Files.cPath[i]) && (Detect_Files.cPath[i] != ','))
  437. i++;
  438. if (Detect_Files.cPath[i] == ',')
  439. i++;
  440. }
  441. return dwRetLast;
  442. }
  443. DWORD CheckFileEx(LPSTR szDir, DETECT_FILES Detect_Files)
  444. {
  445. char szFile[MAX_PATH];
  446. char szRenameFile[MAX_PATH];
  447. DWORD dwInstalledVer, dwInstalledBuild;
  448. DWORD dwRet = DET_NOTINSTALLED;
  449. if (*szDir)
  450. {
  451. lstrcpy(szFile, szDir);
  452. AddPath(szFile, Detect_Files.szFilename);
  453. if (Detect_Files.dwMSVer == (DWORD)-1)
  454. {
  455. if (GetFileAttributes(szFile) != 0xFFFFFFFF)
  456. dwRet = DET_INSTALLED;
  457. }
  458. else
  459. {
  460. ReadFromWininitOrPFRO(szFile, szRenameFile);
  461. if (*szRenameFile != '\0')
  462. GetVersionFromFile(szRenameFile, &dwInstalledVer, &dwInstalledBuild, TRUE);
  463. else
  464. GetVersionFromFile(szFile, &dwInstalledVer, &dwInstalledBuild, TRUE);
  465. if (dwInstalledVer != 0)
  466. dwRet = CompareVersions(Detect_Files.dwMSVer, Detect_Files.dwLSVer, dwInstalledVer, dwInstalledBuild);
  467. }
  468. }
  469. return dwRet;
  470. }
  471. DWORD WINAPI DetectFile(DETECTION_STRUCT *pDet, LPSTR pszFilename)
  472. {
  473. DWORD dwRet = DET_NOTINSTALLED;
  474. DWORD dwInstalledVer, dwInstalledBuild;
  475. char szFile[MAX_PATH];
  476. char szRenameFile[MAX_PATH];
  477. dwInstalledVer = (DWORD) -1;
  478. dwInstalledBuild = (DWORD) -1;
  479. GetSystemDirectory(szFile, sizeof(szFile));
  480. AddPath(szFile, pszFilename);
  481. ReadFromWininitOrPFRO(szFile, szRenameFile);
  482. if (*szRenameFile != '\0')
  483. GetVersionFromFile(szRenameFile, &dwInstalledVer, &dwInstalledBuild, TRUE);
  484. else
  485. GetVersionFromFile(szFile, &dwInstalledVer, &dwInstalledBuild, TRUE);
  486. if (dwInstalledVer != 0)
  487. dwRet = CompareVersions(pDet->dwAskVer, pDet->dwAskBuild, dwInstalledVer, dwInstalledBuild);
  488. if (pDet->pdwInstalledVer && pDet->pdwInstalledBuild)
  489. {
  490. *(pDet->pdwInstalledVer) = dwInstalledVer;
  491. *(pDet->pdwInstalledBuild) = dwInstalledBuild;
  492. }
  493. return dwRet;
  494. }