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.

501 lines
14 KiB

  1. #include <windows.h>
  2. #include "cdinst.h"
  3. VOID ParseCmdLine(LPSTR pszCmdLine)
  4. {
  5. LPSTR pszCurrArg;
  6. LPSTR pszPtr;
  7. GetNextField(&pszCmdLine, "/", 0); // point to the first argument
  8. while ((pszCurrArg = GetNextField(&pszCmdLine, "/", 0)) != NULL)
  9. {
  10. switch (*pszCurrArg)
  11. {
  12. case 's':
  13. case 'S':
  14. if (*++pszCurrArg == ':')
  15. pszCurrArg++;
  16. // Source dir from where to grab the files
  17. if ((pszPtr = Trim(GetNextField(&pszCurrArg, ",", REMOVE_QUOTES))) != NULL)
  18. lstrcpy(g_szSrcDir, pszPtr);
  19. else
  20. *g_szSrcDir = '\0';
  21. break;
  22. case 'd':
  23. case 'D':
  24. if (*++pszCurrArg == ':')
  25. pszCurrArg++;
  26. // Destination dir to where to copy the files
  27. if ((pszPtr = Trim(GetNextField(&pszCurrArg, ",", REMOVE_QUOTES))) != NULL)
  28. lstrcpy(g_szDstDir, pszPtr);
  29. else
  30. *g_szDstDir = '\0';
  31. break;
  32. default: // ignore these arguments
  33. break;
  34. }
  35. }
  36. }
  37. DWORD ReadSectionFromInf(LPCSTR pcszSecName, LPSTR *ppszBuf, PDWORD pdwBufLen, LPCSTR pcszInfName)
  38. {
  39. DWORD dwRet;
  40. // set the file attrib of pcszInfName to NORMAL so that GetPrivateProfileSecion doesn't
  41. // barf in case pcszInfName is read only
  42. SetFileAttributes(pcszInfName, FILE_ATTRIBUTE_NORMAL);
  43. // keep allocating buffers in increasing size of 1K till the entire section is read
  44. *ppszBuf = NULL;
  45. *pdwBufLen = 1024;
  46. do
  47. {
  48. if (*ppszBuf != NULL)
  49. LocalFree(*ppszBuf); // free the previously allocated memory
  50. if (*pdwBufLen == MAX_BUF_LEN)
  51. (*pdwBufLen)--; // 32K - 1 is the size limit for a section
  52. if ((*ppszBuf = (LPSTR) LocalAlloc(LPTR, *pdwBufLen)) == NULL)
  53. {
  54. *pdwBufLen = 0;
  55. return 0;
  56. }
  57. } while ((dwRet = GetPrivateProfileSection(pcszSecName, *ppszBuf, *pdwBufLen, pcszInfName)) == *pdwBufLen - 2 &&
  58. (*pdwBufLen += 1024) <= MAX_BUF_LEN);
  59. return dwRet;
  60. }
  61. BOOL PathExists(LPCSTR pcszDir)
  62. {
  63. DWORD dwAttrib = GetFileAttributes(pcszDir);
  64. return (dwAttrib != (DWORD) -1) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
  65. }
  66. BOOL FileExists(LPCSTR pcszFileName)
  67. {
  68. DWORD dwAttrib = GetFileAttributes(pcszFileName);
  69. if (dwAttrib == (DWORD) -1)
  70. return FALSE;
  71. return !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
  72. }
  73. DWORD FileSize(LPCSTR pcszFile)
  74. {
  75. DWORD dwFileSize = 0;
  76. WIN32_FIND_DATA FindFileData;
  77. HANDLE hFile;
  78. if (pcszFile == NULL || *pcszFile == '\0')
  79. return dwFileSize;
  80. if ((hFile = FindFirstFile(pcszFile, &FindFileData)) != INVALID_HANDLE_VALUE)
  81. {
  82. // assumption here is that the size of the file doesn't exceed 4 gigs
  83. dwFileSize = FindFileData.nFileSizeLow;
  84. FindClose(hFile);
  85. }
  86. return dwFileSize;
  87. }
  88. LPSTR AddPath(LPSTR pszPath, LPCSTR pcszFileName)
  89. {
  90. LPSTR pszPtr;
  91. if (pszPath == NULL)
  92. return NULL;
  93. pszPtr = pszPath + lstrlen(pszPath);
  94. if (pszPtr > pszPath && *CharPrev(pszPath, pszPtr) != '\\')
  95. *pszPtr++ = '\\';
  96. if (pcszFileName != NULL)
  97. lstrcpy(pszPtr, pcszFileName);
  98. else
  99. *pszPtr = '\0';
  100. return pszPath;
  101. }
  102. BOOL PathIsUNCServer(LPCSTR pcszPath)
  103. {
  104. if (PathIsUNC(pcszPath))
  105. {
  106. int i = 0;
  107. for ( ; pcszPath != NULL && *pcszPath; pcszPath = CharNext(pcszPath))
  108. if (*pcszPath == '\\')
  109. i++;
  110. return i == 2;
  111. }
  112. return FALSE;
  113. }
  114. BOOL PathIsUNCServerShare(LPCSTR pcszPath)
  115. {
  116. if (PathIsUNC(pcszPath))
  117. {
  118. int i = 0;
  119. for ( ; pcszPath != NULL && *pcszPath; pcszPath = CharNext(pcszPath))
  120. if (*pcszPath == '\\')
  121. i++;
  122. return i == 3;
  123. }
  124. return FALSE;
  125. }
  126. BOOL PathCreatePath(LPCSTR pcszPathToCreate)
  127. {
  128. CHAR szPath[MAX_PATH];
  129. LPSTR pszPtr;
  130. if (pcszPathToCreate == NULL || lstrlen(pcszPathToCreate) <= 3)
  131. return FALSE;
  132. // eliminate relative paths
  133. if (!PathIsFullPath(pcszPathToCreate) && !PathIsUNC(pcszPathToCreate))
  134. return FALSE;
  135. if (PathIsUNCServer(pcszPathToCreate) || PathIsUNCServerShare(pcszPathToCreate))
  136. return FALSE;
  137. lstrcpy(szPath, pcszPathToCreate);
  138. // chop off the trailing backslash, if it exists
  139. pszPtr = CharPrev(szPath, szPath + lstrlen(szPath));
  140. if (*pszPtr == '\\')
  141. *pszPtr = '\0';
  142. // if it's a UNC path, seek up to the first dir after the share name
  143. if (PathIsUNC(szPath))
  144. {
  145. INT i;
  146. pszPtr = &szPath[2];
  147. for (i = 0; i < 2; i++)
  148. for ( ; *pszPtr != '\\'; pszPtr = CharNext(pszPtr))
  149. ;
  150. pszPtr = CharNext(pszPtr);
  151. }
  152. else // otherwise, just point to the beginning of the first dir
  153. pszPtr = &szPath[3];
  154. for ( ; *pszPtr; pszPtr = CharNext(pszPtr))
  155. {
  156. CHAR ch;
  157. // skip the non-backslash chars
  158. while (*pszPtr && *pszPtr != '\\')
  159. pszPtr = CharNext(pszPtr);
  160. // save the current char
  161. ch = *pszPtr;
  162. *pszPtr = '\0';
  163. if (GetFileAttributes(szPath) == 0xFFFFFFFF) // dir doesn't exist
  164. if (!CreateDirectory(szPath, NULL))
  165. return FALSE;
  166. // restore the current char
  167. *pszPtr = ch;
  168. }
  169. return TRUE;
  170. }
  171. VOID ErrorMsg(UINT uStringID)
  172. {
  173. ErrorMsg(uStringID, "", "");
  174. }
  175. VOID ErrorMsg(UINT uStringID, LPCSTR pcszParam1, LPCSTR pcszParam2)
  176. {
  177. LPSTR pszTextString;
  178. pszTextString = FormatMessageString(uStringID, pcszParam1, pcszParam2);
  179. MessageBox(NULL, (pszTextString != NULL) ? pszTextString : "", g_szTitle, MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK);
  180. if (pszTextString != NULL)
  181. LocalFree(pszTextString);
  182. }
  183. INT ErrorMsg(UINT uStringID, DWORD dwParam1, DWORD dwParam2)
  184. {
  185. INT iRet;
  186. LPSTR pszTextString;
  187. pszTextString = FormatMessageString(uStringID, dwParam1, dwParam2);
  188. iRet = MessageBox(NULL, (pszTextString != NULL) ? pszTextString : "", g_szTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 | MB_SETFOREGROUND);
  189. if (pszTextString != NULL)
  190. LocalFree(pszTextString);
  191. return iRet;
  192. }
  193. LPSTR FormatMessageString(UINT uStringID, LPCSTR pcszParam1, LPCSTR pcszParam2)
  194. {
  195. CHAR szBuf[512];
  196. if (LoadString(g_hInst, uStringID, szBuf, sizeof(szBuf)))
  197. {
  198. LPSTR pszTextString;
  199. if ((pszTextString = FormatString(szBuf, pcszParam1, pcszParam2)) != NULL)
  200. return pszTextString;
  201. }
  202. return NULL;
  203. }
  204. LPSTR FormatMessageString(UINT uStringID, DWORD dwParam1, DWORD dwParam2)
  205. {
  206. CHAR szBuf[512];
  207. if (LoadString(g_hInst, uStringID, szBuf, sizeof(szBuf)))
  208. {
  209. LPSTR pszTextString;
  210. if ((pszTextString = FormatString(szBuf, dwParam1, dwParam2)) != NULL)
  211. return pszTextString;
  212. }
  213. return NULL;
  214. }
  215. LPSTR FormatString(LPCSTR pcszFormatString, ...)
  216. {
  217. va_list vaArgs;
  218. LPSTR pszOutString = NULL;
  219. va_start(vaArgs, pcszFormatString);
  220. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING,
  221. (LPCVOID) pcszFormatString, 0, 0, (PSTR) &pszOutString, 0, &vaArgs);
  222. va_end(vaArgs);
  223. return pszOutString;
  224. }
  225. LPSTR GetNextField(LPSTR *ppszData, LPCSTR pcszDeLims, DWORD dwFlags)
  226. // If (dwFlags & IGNORE_QUOTES) is TRUE, then look for any char in pcszDeLims in *ppszData. If found,
  227. // replace it with the '\0' char and set *ppszData to point to the beginning of the next field and return
  228. // pointer to current field.
  229. //
  230. // If (dwFlags & IGNORE_QUOTES) is FALSE, then look for any char in pcszDeLims outside of balanced quoted sub-strings
  231. // in *ppszData. If found, replace it with the '\0' char and set *ppszData to point to the beginning of
  232. // the next field and return pointer to current field.
  233. //
  234. // If (dwFlags & REMOVE_QUOTES) is TRUE, then remove the surrounding quotes and replace two consecutive quotes by one.
  235. //
  236. // NOTE: If IGNORE_QUOTES and REMOVE_QUOTES are both specified, then IGNORE_QUOTES takes precedence over REMOVE_QUOTES.
  237. //
  238. // If you just want to remove the quotes from a string, call this function as
  239. // GetNextField(&pszData, "\"" or "'" or "", REMOVE_QUOTES).
  240. //
  241. // If you call this function as GetNextField(&pszData, "\"" or "'" or "", 0), you will get back the
  242. // entire pszData as the field.
  243. //
  244. {
  245. LPSTR pszRetPtr, pszPtr;
  246. BOOL fWithinQuotes = FALSE, fRemoveQuote;
  247. CHAR chQuote;
  248. if (ppszData == NULL || *ppszData == NULL || **ppszData == '\0')
  249. return NULL;
  250. for (pszRetPtr = pszPtr = *ppszData; *pszPtr; pszPtr = CharNext(pszPtr))
  251. {
  252. if (!(dwFlags & IGNORE_QUOTES) && (*pszPtr == '"' || *pszPtr == '\''))
  253. {
  254. fRemoveQuote = FALSE;
  255. if (*pszPtr == *(pszPtr + 1)) // two consecutive quotes become one
  256. {
  257. pszPtr++;
  258. if (dwFlags & REMOVE_QUOTES)
  259. fRemoveQuote = TRUE;
  260. else
  261. {
  262. // if pcszDeLims is '"' or '\'', then *pszPtr == pcszDeLims would
  263. // be TRUE and we would break out of the loop against the design specs;
  264. // to prevent this just continue
  265. continue;
  266. }
  267. }
  268. else if (!fWithinQuotes)
  269. {
  270. fWithinQuotes = TRUE;
  271. chQuote = *pszPtr; // save the quote char
  272. fRemoveQuote = dwFlags & REMOVE_QUOTES;
  273. }
  274. else
  275. {
  276. if (*pszPtr == chQuote) // match the correct quote char
  277. {
  278. fWithinQuotes = FALSE;
  279. fRemoveQuote = dwFlags & REMOVE_QUOTES;
  280. }
  281. }
  282. if (fRemoveQuote)
  283. {
  284. // shift the entire string one char to the left to get rid of the quote char
  285. MoveMemory(pszPtr, pszPtr + 1, lstrlen(pszPtr));
  286. }
  287. }
  288. // BUGBUG: Is type casting pszPtr to UNALIGNED necessary? -- copied it from ANSIStrChr
  289. // check if pszPtr is pointing to one of the chars in pcszDeLims
  290. if (!fWithinQuotes &&
  291. ANSIStrChr(pcszDeLims, (WORD) (IsDBCSLeadByte(*pszPtr) ? *((UNALIGNED WORD *) pszPtr) : *pszPtr)) != NULL)
  292. break;
  293. }
  294. // NOTE: if fWithinQuotes is TRUE here, then we have an unbalanced quoted string; but we don't care!
  295. // the entire string after the beginning quote becomes the field
  296. if (*pszPtr) // pszPtr is pointing to a char in pcszDeLims
  297. {
  298. *ppszData = CharNext(pszPtr); // save the pointer to the beginning of next field in *ppszData
  299. *pszPtr = '\0'; // replace the DeLim char with the '\0' char
  300. }
  301. else
  302. *ppszData = pszPtr; // we have reached the end of the string; next call to this function
  303. // would return NULL
  304. return pszRetPtr;
  305. }
  306. LPSTR Trim(LPSTR pszData)
  307. // Trim the leading and trailing white space chars in pszData
  308. {
  309. LPSTR pszRetPtr;
  310. if (pszData == NULL)
  311. return NULL;
  312. // trim the leading white space chars
  313. for ( ; *pszData; pszData = CharNext(pszData))
  314. if (!IsSpace(*pszData))
  315. break;
  316. // save the return ptr
  317. pszRetPtr = pszData;
  318. // go to the end and start trimming the trailing white space chars
  319. pszData += lstrlen(pszData);
  320. while ((pszData = CharPrev(pszRetPtr, pszData)) != pszRetPtr)
  321. if (!IsSpace(*pszData))
  322. break;
  323. if (*pszData)
  324. {
  325. pszData = CharNext(pszData);
  326. *pszData = '\0';
  327. }
  328. return pszRetPtr;
  329. }
  330. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  331. /*
  332. * StrChr - Find first occurrence of character in string
  333. * Assumes lpStart points to start of null terminated string
  334. * wMatch is the character to match
  335. * returns ptr to the first occurrence of ch in str, NULL if not found.
  336. */
  337. LPSTR FAR ANSIStrChr(LPCSTR lpStart, WORD wMatch)
  338. {
  339. for ( ; *lpStart; lpStart = CharNext(lpStart))
  340. {
  341. // (ChrCmp returns FALSE when characters match)
  342. if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch))
  343. return((LPSTR)lpStart);
  344. }
  345. return (NULL);
  346. }
  347. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  348. /*
  349. * StrRChr - Find last occurrence of character in string
  350. * Assumes lpStart points to start of null terminated string
  351. * wMatch is the character to match
  352. * returns ptr to the last occurrence of ch in str, NULL if not found.
  353. */
  354. LPSTR FAR ANSIStrRChr(LPCSTR lpStart, WORD wMatch)
  355. {
  356. LPCSTR lpFound = NULL;
  357. for ( ; *lpStart; lpStart = CharNext(lpStart))
  358. {
  359. // (ChrCmp returns FALSE when characters match)
  360. if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch))
  361. lpFound = lpStart;
  362. }
  363. return ((LPSTR)lpFound);
  364. }
  365. // copied from \\trango\slmadd\src\shell\shlwapi\strings.c
  366. /*
  367. * ChrCmp - Case sensitive character comparison for DBCS
  368. * Assumes w1, wMatch are characters to be compared
  369. * Return FALSE if they match, TRUE if no match
  370. */
  371. __inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch)
  372. {
  373. /* Most of the time this won't match, so test it first for speed.
  374. */
  375. if (LOBYTE(w1) == LOBYTE(wMatch))
  376. {
  377. if (IsDBCSLeadByte(LOBYTE(w1)))
  378. {
  379. return(w1 != wMatch);
  380. }
  381. return FALSE;
  382. }
  383. return TRUE;
  384. }