Source code of Windows XP (NT5)
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.

363 lines
8.5 KiB

  1. #include <stdio.h>
  2. #include <direct.h>
  3. #include <windows.h>
  4. #include "patchapi.h"
  5. #include "const.h"
  6. BOOL IsUnicodeFile(IN HANDLE hFile);
  7. BOOL ReadLine(IN HANDLE hFile, IN WCHAR* strLine);
  8. BOOL CopyThisFile(IN WCHAR* strFrom, IN WCHAR* strTo);
  9. BOOL MoveThisFile(IN WCHAR* strFrom, IN WCHAR* strTo);
  10. BOOL PatchFile(IN WCHAR* strOldFile, IN WCHAR* strPatchFile, IN WCHAR* strNewFile);
  11. BOOL CreateZeroFile(IN WCHAR* strFile);
  12. BOOL CreateThisDirectory(IN WCHAR* strDirectory, IN WCHAR* strAttrib);
  13. BOOL DeleteThisDirectory(IN WCHAR* strDirectory);
  14. extern "C" VOID __cdecl wmain(VOID)
  15. {
  16. HANDLE hScriptFile = CreateFileW(APPLY_PATCH_SCRIPT,
  17. GENERIC_READ,
  18. 0,
  19. NULL,
  20. OPEN_EXISTING,
  21. FILE_ATTRIBUTE_NORMAL,
  22. NULL);
  23. if(hScriptFile != INVALID_HANDLE_VALUE)
  24. {
  25. if(IsUnicodeFile(hScriptFile))
  26. {
  27. // local varibles
  28. BOOL blnReturn = TRUE;
  29. WCHAR strThisLine[SUPER_LENGTH / 2];
  30. WCHAR* strAction = NULL;
  31. WCHAR strParam1[STRING_LENGTH];
  32. WCHAR strParam2[STRING_LENGTH];
  33. WCHAR strParam3[STRING_LENGTH];
  34. DWORD iError = 0;
  35. // get drive letter
  36. INT iDrive = _getdrive() - 1;
  37. if(iDrive >= 0)
  38. {
  39. strParam1[0] = strParam2[0] = strParam3[0] = (WCHAR)(L'A' + iDrive);
  40. strParam1[1] = strParam2[1] = strParam3[1] = L':';
  41. while(ReadLine(hScriptFile, strThisLine))
  42. {
  43. blnReturn = TRUE;
  44. strParam1[2] = strParam2[2] = strParam3[2] = 0;
  45. strAction = wcstok(strThisLine, SEPARATOR);
  46. if(strAction)
  47. {
  48. switch(strAction[0])
  49. {
  50. case ACTION_C_NEW_DIRECTORY:
  51. wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
  52. blnReturn = CreateThisDirectory(strParam1, wcstok(NULL, SEPARATOR));
  53. break;
  54. case ACTION_C_PATCH_FILE:
  55. wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
  56. wcscpy(strParam2 + 2, wcstok(NULL, SEPARATOR));
  57. wcscpy(strParam3 + 2, wcstok(NULL, SEPARATOR));
  58. blnReturn = PatchFile(strParam1, strParam2, strParam3);
  59. break;
  60. case ACTION_C_MOVE_FILE:
  61. case ACTION_C_EXCEPT_FILE:
  62. case ACTION_C_RENAME_FILE:
  63. case ACTION_C_NOT_PATCH_FILE:
  64. case ACTION_C_SAVED_FILE:
  65. wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
  66. wcscpy(strParam2 + 2, wcstok(NULL, SEPARATOR));
  67. blnReturn = MoveThisFile(strParam1, strParam2);
  68. break;
  69. case ACTION_C_COPY_FILE:
  70. wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
  71. wcscpy(strParam2 + 2, wcstok(NULL, SEPARATOR));
  72. blnReturn = CopyThisFile(strParam1, strParam2);
  73. break;
  74. case ACTION_C_NEW_ZERO_FILE:
  75. wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
  76. blnReturn = CreateZeroFile(strParam1);
  77. break;
  78. case ACTION_C_DELETE_DIRECTORY:
  79. wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
  80. blnReturn = DeleteThisDirectory(strParam1);
  81. break;
  82. default:
  83. blnReturn = FALSE;
  84. break;
  85. }
  86. }
  87. if(!blnReturn)
  88. {
  89. iError = GetLastError();
  90. switch(iError)
  91. {
  92. case ERROR_PATCH_NOT_NECESSARY:
  93. CopyThisFile(strParam1, strParam3);
  94. break;
  95. default:
  96. // some thing went wrong
  97. printf("warning, A=%ls, 1=%ls, 2=%ls, 3=%ls, C=%d\n", strAction, strParam1, strParam2, strParam3, iError);
  98. break;
  99. }
  100. }
  101. }
  102. }
  103. }
  104. CloseHandle(hScriptFile);
  105. }
  106. }
  107. BOOL IsUnicodeFile(IN HANDLE hFile)
  108. {
  109. WCHAR cFirstChar = 0;
  110. ULONG iRead = 0;
  111. if(hFile != INVALID_HANDLE_VALUE &&
  112. ReadFile(hFile, &cFirstChar, sizeof(WCHAR), &iRead, NULL) &&
  113. iRead != 0 &&
  114. cFirstChar == UNICODE_HEAD)
  115. {
  116. return(TRUE);
  117. }
  118. return(FALSE);
  119. }
  120. BOOL ReadLine(IN HANDLE hFile, IN WCHAR* strLine)
  121. {
  122. static WCHAR strBuffer[SUPER_LENGTH + 1];
  123. static LONG iLength = 0;
  124. static LONG iReadChar = 0;
  125. static ULONG iRead = 0;
  126. static LONG iOffset = 0;
  127. static LONG iThisLineLength = 0;
  128. static WCHAR* strThisLine = NULL;
  129. if(iLength > 0)
  130. {
  131. // char 0xA is set to 0
  132. strThisLine = wcstok(strBuffer + iReadChar - iLength, CRETURN);
  133. iThisLineLength = wcslen(strThisLine);
  134. if(iThisLineLength + 1 <= iLength)
  135. {
  136. // char 0xD is set to 0
  137. strThisLine[iThisLineLength - 1] = 0;
  138. wcscpy(strLine, strThisLine);
  139. iLength = iLength - iThisLineLength - 1;
  140. }
  141. else
  142. {
  143. wcsncpy(strLine, strThisLine, iLength);
  144. // set the last char + 1 to 0 for cat
  145. strLine[iLength] = 0;
  146. if(iLength <= 0 || strLine[iLength - 1] != ENDOFLINE[0])
  147. {
  148. ReadFile(hFile, strBuffer, SUPER_LENGTH * sizeof(WCHAR), &iRead, NULL);
  149. iReadChar = iRead / sizeof(WCHAR);
  150. // char 0xA is set to 0
  151. strThisLine = wcstok(strBuffer, CRETURN);
  152. iThisLineLength = wcslen(strThisLine);
  153. iLength = iReadChar - iThisLineLength - 1;
  154. // char 0xD is set to 0
  155. strThisLine[iThisLineLength - 1] = 0;
  156. wcscat(strLine, strThisLine);
  157. if(strBuffer[0] == CRETURN[0])
  158. {
  159. iLength -= 1;
  160. }
  161. }
  162. else
  163. {
  164. strLine[iLength - 1] = 0;
  165. iLength = 0;
  166. }
  167. }
  168. }
  169. else
  170. {
  171. if(ReadFile(hFile, strBuffer, SUPER_LENGTH * sizeof(WCHAR), &iRead, NULL) && iRead != 0)
  172. {
  173. iReadChar = iRead / sizeof(WCHAR);
  174. // char 0xA is set to 0
  175. strThisLine = wcstok(strBuffer, CRETURN);
  176. iThisLineLength = wcslen(strThisLine);
  177. iLength = iReadChar - iThisLineLength - 1;
  178. // char 0xD is set to 0
  179. strThisLine[iThisLineLength - 1] = 0;
  180. wcscpy(strLine, strThisLine);
  181. if(strBuffer[0] == CRETURN[0])
  182. {
  183. iLength -= 1;
  184. }
  185. }
  186. else
  187. {
  188. return(FALSE);
  189. }
  190. }
  191. return(TRUE);
  192. }
  193. BOOL CopyThisFile(IN WCHAR* strFrom, IN WCHAR* strTo)
  194. {
  195. BOOL blnReturn = TRUE;
  196. blnReturn = CopyFileW(strFrom, strTo, TRUE);
  197. return(blnReturn);
  198. }
  199. BOOL MoveThisFile(IN WCHAR* strFrom, IN WCHAR* strTo)
  200. {
  201. BOOL blnReturn = FALSE;
  202. DWORD iAttrib = GetFileAttributesW(strFrom);
  203. if(iAttrib != 0xFFFFFFFF)
  204. {
  205. blnReturn = SetFileAttributesW(strFrom, FILE_ATTRIBUTE_ARCHIVE);
  206. blnReturn &= MoveFileW(strFrom, strTo);
  207. blnReturn &= SetFileAttributesW(strTo, iAttrib);
  208. }
  209. return(blnReturn);
  210. }
  211. BOOL CreateZeroFile(IN WCHAR* strFile)
  212. {
  213. BOOL blnReturn = TRUE;
  214. HANDLE hFile = CreateFileW(strFile,
  215. GENERIC_READ | GENERIC_WRITE,
  216. 0, NULL,
  217. CREATE_ALWAYS,
  218. FILE_ATTRIBUTE_NORMAL,
  219. NULL);
  220. if((blnReturn = (hFile != INVALID_HANDLE_VALUE)) == TRUE)
  221. {
  222. CloseHandle(hFile);
  223. }
  224. return(blnReturn);
  225. }
  226. BOOL PatchFile(IN WCHAR* strOldFile, IN WCHAR* strPatchFile, IN WCHAR* strNewFile)
  227. {
  228. BOOL blnReturn = TRUE;
  229. blnReturn = ApplyPatchToFileW(strPatchFile,
  230. strOldFile,
  231. strNewFile,
  232. 0);
  233. return(blnReturn);
  234. }
  235. BOOL CreateThisDirectory(IN WCHAR* strDirectory, IN WCHAR* strAttrib)
  236. {
  237. BOOL blnReturn = TRUE;
  238. blnReturn = (_wmkdir(strDirectory) == 0 || errno == 17 /*EEXIST*/);
  239. if(blnReturn && strAttrib)
  240. {
  241. DWORD iAttrib = 0;
  242. for(UINT i = 0; i < wcslen(strAttrib); i++)
  243. {
  244. switch(strAttrib[i])
  245. {
  246. case DIR_C_READONLY:
  247. iAttrib |= FILE_ATTRIBUTE_READONLY;
  248. break;
  249. case DIR_C_SYSTEM:
  250. iAttrib |= FILE_ATTRIBUTE_SYSTEM;
  251. break;
  252. case DIR_C_HIDDEN:
  253. iAttrib |= FILE_ATTRIBUTE_HIDDEN;
  254. break;
  255. case DIR_C_COMPRESSED:
  256. iAttrib |= FILE_ATTRIBUTE_COMPRESSED;
  257. break;
  258. case DIR_C_ENCRYPTED:
  259. iAttrib |= FILE_ATTRIBUTE_ENCRYPTED;
  260. break;
  261. default:
  262. break;
  263. }
  264. }
  265. SetFileAttributesW(strDirectory, iAttrib);
  266. }
  267. return(blnReturn);
  268. }
  269. BOOL DeleteThisDirectory(IN WCHAR* strDirectory)
  270. {
  271. INT length = 0;
  272. BOOL result = TRUE;
  273. HANDLE findHandle = INVALID_HANDLE_VALUE;
  274. WIN32_FIND_DATAW file;
  275. WCHAR path[MAXPATH + 7];
  276. if((length = wcslen(strDirectory)) > MAXPATH)
  277. {
  278. result = FALSE;
  279. goto done;
  280. }
  281. wcscpy(path, strDirectory);
  282. if(length)
  283. {
  284. if((path[length - 1] != '\\') AND (path[length - 1] != ':'))
  285. {
  286. wcscpy(path + length, L"\\");
  287. length++;
  288. }
  289. }
  290. wcscpy(path + length, L"*.*");
  291. findHandle = FindFirstFileW(path, &file);
  292. if(findHandle == INVALID_HANDLE_VALUE)
  293. {
  294. result = FALSE;
  295. }
  296. path[length] = L'\0';
  297. while(result)
  298. {
  299. if((file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY &&
  300. wcscmp(file.cFileName, L".") != 0 &&
  301. wcscmp(file.cFileName, L"..") != 0)
  302. {
  303. /* recursively going into this directory */
  304. wcscpy(path + length, file.cFileName);
  305. DeleteThisDirectory(path);
  306. }
  307. else
  308. {
  309. wcscpy(path + length, file.cFileName);
  310. if(!DeleteFileW(path))
  311. {
  312. SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
  313. DeleteFileW(path);
  314. }
  315. }
  316. path[length] = 0;
  317. if(!FindNextFileW(findHandle, &file))
  318. {
  319. result = FALSE;
  320. }
  321. }
  322. /* All files are examed, close the findhandle */
  323. if(findHandle != INVALID_HANDLE_VALUE)
  324. {
  325. FindClose(findHandle);
  326. findHandle = INVALID_HANDLE_VALUE;
  327. }
  328. done:
  329. /* finally remove the directory */
  330. return(RemoveDirectoryW(path));
  331. }