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.

800 lines
25 KiB

  1. #include <tchar.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <windows.h>
  5. void ShowHelp(void);
  6. LPSTR StripWhitespace(LPSTR pszString);
  7. LPWSTR MakeWideStrFromAnsi(UINT uiCodePage, LPSTR psz);
  8. int Ansi2Unicode(TCHAR * szAnsiFile_input,TCHAR * szUnicodeFile_output,UINT iCodePage);
  9. int IsFileUnicode(TCHAR * szFile_input);
  10. int StripControlZfromUnicodeFile(TCHAR * szFilePath1,TCHAR * szFilePath2);
  11. //***************************************************************************
  12. //*
  13. //* purpose: main
  14. //*
  15. //***************************************************************************
  16. int __cdecl main(int argc,char *argv[])
  17. {
  18. int iRet = 0;
  19. int argno;
  20. char * pArg = NULL;
  21. char * pCmdStart = NULL;
  22. TCHAR szFilePath1[_MAX_PATH];
  23. TCHAR szFilePath2[_MAX_PATH];
  24. TCHAR szParamString_C[_MAX_PATH];
  25. TCHAR szParamString_H[50];
  26. TCHAR szParamString_M[_MAX_PATH];
  27. int iDoAnsi2Unicode = FALSE;
  28. int iDoIsUnicodeCheck = FALSE;
  29. int iDoUnicodeStripControlZ = FALSE;
  30. int iDoVersion = FALSE;
  31. int iGotParamC = FALSE;
  32. int iGotParamH = FALSE;
  33. int iGotParamM = FALSE;
  34. *szFilePath1 = '\0';
  35. *szFilePath2 = '\0';
  36. *szParamString_C = '\0';
  37. *szParamString_H = '\0';
  38. *szParamString_M = '\0';
  39. _tcscpy(szFilePath1,_T(""));
  40. _tcscpy(szFilePath2,_T(""));
  41. _tcscpy(szParamString_C,_T(""));
  42. _tcscpy(szParamString_H,_T(""));
  43. _tcscpy(szParamString_M,_T(""));
  44. for(argno=1; argno<argc; argno++)
  45. {
  46. if ( argv[argno][0] == '-' || argv[argno][0] == '/' )
  47. {
  48. switch (argv[argno][1])
  49. {
  50. case 'a':
  51. case 'A':
  52. iDoAnsi2Unicode = TRUE;
  53. break;
  54. case 'i':
  55. case 'I':
  56. iDoIsUnicodeCheck = TRUE;
  57. break;
  58. case 'z':
  59. case 'Z':
  60. iDoUnicodeStripControlZ = TRUE;
  61. break;
  62. case 'v':
  63. case 'V':
  64. iDoVersion = TRUE;
  65. break;
  66. case 'c':
  67. case 'C':
  68. // Get the string for this flag
  69. pArg = CharNextA(argv[argno]);
  70. pArg = CharNextA(pArg);
  71. if (*pArg == ':')
  72. {
  73. char szTempString[_MAX_PATH];
  74. pArg = CharNextA(pArg);
  75. // Check if it's quoted
  76. if (*pArg == '\"')
  77. {
  78. pArg = CharNextA(pArg);
  79. pCmdStart = pArg;
  80. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  81. }
  82. else
  83. {
  84. pCmdStart = pArg;
  85. while (*pArg){pArg = CharNextA(pArg);}
  86. }
  87. *pArg = '\0';
  88. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  89. // Convert to unicode
  90. #if defined(UNICODE) || defined(_UNICODE)
  91. MultiByteToWideChar(CP_ACP, 0, szTempString, -1, (LPWSTR) szParamString_C, _MAX_PATH);
  92. #else
  93. _tcscpy(szParamString_C,szTempString);
  94. #endif
  95. iGotParamC = TRUE;
  96. }
  97. break;
  98. case 'h':
  99. case 'H':
  100. // Get the string for this flag
  101. pArg = CharNextA(argv[argno]);
  102. pArg = CharNextA(pArg);
  103. if (*pArg == ':')
  104. {
  105. char szTempString[_MAX_PATH];
  106. pArg = CharNextA(pArg);
  107. // Check if it's quoted
  108. if (*pArg == '\"')
  109. {
  110. pArg = CharNextA(pArg);
  111. pCmdStart = pArg;
  112. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  113. }
  114. else
  115. {
  116. pCmdStart = pArg;
  117. while (*pArg){pArg = CharNextA(pArg);}
  118. }
  119. *pArg = '\0';
  120. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  121. // Convert to unicode
  122. #if defined(UNICODE) || defined(_UNICODE)
  123. MultiByteToWideChar(CP_ACP, 0, szTempString, -1, (LPWSTR) szParamString_H, _MAX_PATH);
  124. #else
  125. _tcscpy(szParamString_H,szTempString);
  126. #endif
  127. iGotParamH = TRUE;
  128. }
  129. break;
  130. case 'm':
  131. case 'M':
  132. // Get the string for this flag
  133. pArg = CharNextA(argv[argno]);
  134. pArg = CharNextA(pArg);
  135. if (*pArg == ':')
  136. {
  137. char szTempString[_MAX_PATH];
  138. pArg = CharNextA(pArg);
  139. // Check if it's quoted
  140. if (*pArg == '\"')
  141. {
  142. pArg = CharNextA(pArg);
  143. pCmdStart = pArg;
  144. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  145. }
  146. else
  147. {
  148. pCmdStart = pArg;
  149. while (*pArg){pArg = CharNextA(pArg);}
  150. }
  151. *pArg = '\0';
  152. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  153. // Convert to unicode
  154. #if defined(UNICODE) || defined(_UNICODE)
  155. MultiByteToWideChar(CP_ACP, 0, szTempString, -1, (LPWSTR) szParamString_M, _MAX_PATH);
  156. #else
  157. _tcscpy(szParamString_M,szTempString);
  158. #endif
  159. iGotParamM = TRUE;
  160. }
  161. break;
  162. case '?':
  163. goto main_exit_with_help;
  164. break;
  165. }
  166. }
  167. else
  168. {
  169. if (_tcsicmp(szFilePath1, _T("")) == 0)
  170. {
  171. // if no arguments, then get the filename portion
  172. #if defined(UNICODE) || defined(_UNICODE)
  173. MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPTSTR) szFilePath1, _MAX_PATH);
  174. #else
  175. _tcscpy(szFilePath1,argv[argno]);
  176. #endif
  177. }
  178. else
  179. {
  180. if (_tcsicmp(szFilePath2, _T("")) == 0)
  181. {
  182. // if no arguments, then get the filename portion
  183. #if defined(UNICODE) || defined(_UNICODE)
  184. MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPTSTR) szFilePath2, _MAX_PATH);
  185. #else
  186. _tcscpy(szFilePath2,argv[argno]);
  187. #endif
  188. }
  189. }
  190. }
  191. }
  192. //
  193. // Check what were supposed to do
  194. //
  195. if (TRUE == iDoAnsi2Unicode)
  196. {
  197. UINT iCodePage = 1252;
  198. // check for required parameters
  199. if (_tcsicmp(szFilePath1, _T("")) == 0)
  200. {
  201. _tprintf(_T("[-a] parameter missing filename1 parameter\n"));
  202. goto main_exit_with_help;
  203. }
  204. if (_tcsicmp(szFilePath2, _T("")) == 0)
  205. {
  206. _tprintf(_T("[-a] parameter missing filename2 parameter\n"));
  207. goto main_exit_with_help;
  208. }
  209. // check for optional parameter
  210. if (TRUE == iGotParamC)
  211. {
  212. if (_tcsicmp(szParamString_C, _T("")) == 0)
  213. {
  214. // convert it to a number.
  215. iCodePage = _ttoi(szParamString_C);
  216. }
  217. }
  218. // call the function
  219. Ansi2Unicode(szFilePath1,szFilePath2,iCodePage);
  220. iRet = 0;
  221. }
  222. else
  223. {
  224. if (TRUE == iDoUnicodeStripControlZ)
  225. {
  226. // check for required parameters
  227. if (_tcsicmp(szFilePath1, _T("")) == 0)
  228. {
  229. _tprintf(_T("[-z] parameter missing filename1 parameter\n"));
  230. goto main_exit_with_help;
  231. }
  232. if (_tcsicmp(szFilePath2, _T("")) == 0)
  233. {
  234. _tprintf(_T("[-z] parameter missing filename2 parameter\n"));
  235. goto main_exit_with_help;
  236. }
  237. // call the function.
  238. iRet = StripControlZfromUnicodeFile(szFilePath1,szFilePath2);
  239. if (1 == iRet)
  240. {
  241. _tprintf(_T("control-z removed and saved to new file\n"));
  242. }
  243. iRet = 0;
  244. }
  245. }
  246. if (TRUE == iDoIsUnicodeCheck)
  247. {
  248. iRet = 0;
  249. // check for required parameters
  250. if (_tcsicmp(szFilePath1, _T("")) == 0)
  251. {
  252. _tprintf(_T("[-i] parameter missing filename1 parameter\n"));
  253. goto main_exit_with_help;
  254. }
  255. // call the function.
  256. // return 2 if the file is unicode
  257. // return 1 if the file is not unicode
  258. iRet = IsFileUnicode(szFilePath1);
  259. if (2 == iRet)
  260. {
  261. _tprintf(_T("%s is unicode\n"),szFilePath1);
  262. }
  263. else if (1 == iRet)
  264. {
  265. _tprintf(_T("%s is not unicode\n"),szFilePath1);
  266. }
  267. else
  268. {
  269. _tprintf(_T("error with file %s\n"),szFilePath1);
  270. }
  271. }
  272. if (TRUE == iDoVersion)
  273. {
  274. // output the version
  275. _tprintf(_T("1\n\n"));
  276. iRet = 10;
  277. goto main_exit_gracefully;
  278. }
  279. if (TRUE == iGotParamH)
  280. {
  281. // Output hex number
  282. if (_tcsicmp(szParamString_H, _T("")) != 0)
  283. {
  284. DWORD dwMyDecimal = _ttoi(szParamString_H);
  285. if (iGotParamM && (_tcsicmp(szParamString_M, _T("")) != 0))
  286. {
  287. _tprintf(szParamString_M,dwMyDecimal);
  288. }
  289. else
  290. {
  291. // convert it to a hex number
  292. _tprintf(_T("%x\n"),dwMyDecimal);
  293. }
  294. goto main_exit_gracefully;
  295. }
  296. }
  297. if (_tcsicmp(szFilePath1, _T("")) == 0)
  298. {
  299. goto main_exit_with_help;
  300. }
  301. goto main_exit_gracefully;
  302. main_exit_gracefully:
  303. exit(iRet);
  304. main_exit_with_help:
  305. ShowHelp();
  306. exit(iRet);
  307. }
  308. //***************************************************************************
  309. //*
  310. //* purpose: ?
  311. //*
  312. //***************************************************************************
  313. void ShowHelp(void)
  314. {
  315. TCHAR szModuleName[_MAX_PATH];
  316. TCHAR szFilename_only[_MAX_PATH];
  317. // get the modules full pathed filename
  318. if (0 != GetModuleFileName(NULL,(LPTSTR) szModuleName,_MAX_PATH))
  319. {
  320. // Trim off the filename only.
  321. _tsplitpath(szModuleName, NULL, NULL, szFilename_only, NULL);
  322. _tprintf(_T("Unicode File Utility\n\n"));
  323. _tprintf(_T("%s [-a] [-i] [-v] [-z] [-c:codepage] [-h:number] [-m:printf format] [drive:][path]filename1 [drive:][path]filename2\n\n"),szFilename_only);
  324. _tprintf(_T("[-a] paramter -- converting ansi to unicode file:\n"));
  325. _tprintf(_T(" -a required parameter for this functionality\n"));
  326. _tprintf(_T(" -c:codepage specifies the codepage to use (optional,defaults to 1252 (usa ascii))\n"));
  327. _tprintf(_T(" filename1 ansi filename that should be converted\n"));
  328. _tprintf(_T(" filename2 unicode filename that result will be saved to\n\n"));
  329. _tprintf(_T("[-i] parameter -- is specified file unicode:\n"));
  330. _tprintf(_T(" -i required paramter for this functionality\n"));
  331. _tprintf(_T(" filename1 filename to check if unicode. if unicode ERRORLEVEL=2, if not unicode ERRORLEVEL=1.\n"));
  332. _tprintf(_T("[-z] parameter -- removing trailing control-z from end of unicode file:\n"));
  333. _tprintf(_T(" -z required paramter for this functionality\n"));
  334. _tprintf(_T(" filename1 unicode filename that should have control-z removed from\n"));
  335. _tprintf(_T(" filename2 unicode filename that result will be saved to\n\n"));
  336. _tprintf(_T("[-h] parameter -- displaying version:\n"));
  337. _tprintf(_T(" -h:decimalnum required paramter for this functionality, input decimal number, get hex back.\n"));
  338. _tprintf(_T("[-m] parameter -- printf format for -h function:\n"));
  339. _tprintf(_T(" -m:%%x required paramter for this functionality.. eg:%%x,0x%%x,x%%08lx,x8%%07lx\n"));
  340. _tprintf(_T("[-v] parameter -- displaying version:\n"));
  341. _tprintf(_T(" -v required paramter for this functionality, sets ERRORLEVEL=version num of this binary.\n"));
  342. _tprintf(_T("\n"));
  343. _tprintf(_T("Examples:\n"));
  344. _tprintf(_T("%s -a -c:1252 c:\\MyGroup\\MyFileAnsi.txt c:\\MyGroup\\MyFileUnicode.txt\n"),szFilename_only);
  345. _tprintf(_T("%s -i c:\\MyGroup\\MyFileUnicode.txt\n"),szFilename_only);
  346. _tprintf(_T("%s -z c:\\MyGroup\\MyFileUnicode.txt c:\\MyGroup\\MyFileUnicode.txt\n"),szFilename_only);
  347. }
  348. return;
  349. }
  350. //***************************************************************************
  351. //*
  352. //* purpose:
  353. //*
  354. //***************************************************************************
  355. LPSTR StripWhitespace( LPSTR pszString )
  356. {
  357. LPSTR pszTemp = NULL;
  358. if ( pszString == NULL )
  359. {
  360. return NULL;
  361. }
  362. while ( *pszString == ' ' || *pszString == '\t' )
  363. {
  364. pszString += 1;
  365. }
  366. // Catch case where string consists entirely of whitespace or empty string.
  367. if ( *pszString == '\0' )
  368. {
  369. return pszString;
  370. }
  371. pszTemp = pszString;
  372. pszString += lstrlenA(pszString) - 1;
  373. while ( *pszString == ' ' || *pszString == '\t' )
  374. {
  375. *pszString = '\0';
  376. pszString -= 1;
  377. }
  378. return pszTemp;
  379. }
  380. //***************************************************************************
  381. //*
  382. //* purpose: return back a Alocated wide string from a ansi string
  383. //* caller must free the returned back pointer with GlobalFree()
  384. //*
  385. //***************************************************************************
  386. LPWSTR MakeWideStrFromAnsi(UINT uiCodePage, LPSTR psz)
  387. {
  388. LPWSTR pwsz;
  389. int i;
  390. // make sure they gave us something
  391. if (!psz)
  392. {
  393. return NULL;
  394. }
  395. // compute the length
  396. i = MultiByteToWideChar(uiCodePage, 0, psz, -1, NULL, 0);
  397. if (i <= 0) return NULL;
  398. // allocate memory in that length
  399. pwsz = (LPWSTR) GlobalAlloc(GPTR,i * sizeof(WCHAR));
  400. if (!pwsz) return NULL;
  401. // clear out memory
  402. memset(pwsz, 0, wcslen(pwsz) * sizeof(WCHAR));
  403. // convert the ansi string into unicode
  404. i = MultiByteToWideChar(uiCodePage, 0, (LPSTR) psz, -1, pwsz, i);
  405. if (i <= 0)
  406. {
  407. GlobalFree(pwsz);
  408. pwsz = NULL;
  409. return NULL;
  410. }
  411. // make sure ends with null
  412. pwsz[i - 1] = 0;
  413. // return the pointer
  414. return pwsz;
  415. }
  416. //***************************************************************************
  417. //*
  418. //* purpose: converts the ansi file to a unicode file
  419. //*
  420. //***************************************************************************
  421. int Ansi2Unicode(TCHAR * szAnsiFile_input,TCHAR * szUnicodeFile_output,UINT iCodePage)
  422. {
  423. int iReturn = FALSE;
  424. HANDLE hFile = INVALID_HANDLE_VALUE;
  425. DWORD dwFileSize = 0;
  426. unsigned char *pInputFileBuf = NULL;
  427. WCHAR * pwOutputFileBuf = NULL;
  428. DWORD dwBytesReadIn = 0;
  429. DWORD dwBytesWritten = 0;
  430. BYTE bOneByte = 0;
  431. //
  432. // READ INPUT FILE
  433. //
  434. // open the input file with read access
  435. //
  436. hFile = CreateFile((LPCTSTR) szAnsiFile_input, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  437. if( hFile == INVALID_HANDLE_VALUE)
  438. {
  439. _tprintf(_T("Unable to open input file:%s,err=0x%x\n"),szAnsiFile_input,GetLastError());
  440. goto Ansi2Unicode_Exit;
  441. }
  442. // getfile size so we know how much memory we should allocate
  443. dwFileSize = GetFileSize(hFile, NULL);
  444. if (dwFileSize == 0)
  445. {
  446. _tprintf(_T("input file:%s is empty\n"),szAnsiFile_input);
  447. goto Ansi2Unicode_Exit;
  448. }
  449. // allocate the memory the size of the file
  450. if ( ( pInputFileBuf = (unsigned char *) malloc( (size_t) dwFileSize + 1 ) ) == NULL )
  451. {
  452. _tprintf(_T("Out of memory\n"));
  453. goto Ansi2Unicode_Exit;
  454. }
  455. // clear buffer we just created
  456. memset(pInputFileBuf, 0, dwFileSize + 1);
  457. // Read all the data from the file into the buffer
  458. if ( ReadFile( hFile, pInputFileBuf, dwFileSize, &dwBytesReadIn, NULL ) == FALSE )
  459. {
  460. _tprintf(_T("Readfile:%s, error=%s\n"),szAnsiFile_input,strerror(errno));
  461. goto Ansi2Unicode_Exit;
  462. }
  463. // if the amount of data that we read in is different than
  464. // what the file size is then get out... we didn't read all of the data into the buffer.
  465. if (dwFileSize != dwBytesReadIn)
  466. {
  467. _tprintf(_T("Readfile:%s, error file too big to read into memory\n"),szAnsiFile_input);
  468. goto Ansi2Unicode_Exit;
  469. }
  470. // check if the input file is already unicode!
  471. // if it is then just copy the damn file to the new filename!
  472. if (0xFF == pInputFileBuf[0] && 0xFE == pInputFileBuf[1])
  473. {
  474. // file is already unicode!
  475. if (FALSE == CopyFile((LPCTSTR)szAnsiFile_input,(LPCTSTR)szUnicodeFile_output, FALSE))
  476. {
  477. _tprintf(_T("Failed to copy file %s to %s\n"),szAnsiFile_input,szUnicodeFile_output);
  478. }
  479. // we copied the file to the new filename
  480. // we're done
  481. goto Ansi2Unicode_Exit;
  482. }
  483. // close handle to file#1
  484. CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;
  485. //
  486. // CREATE OUTPUT FILE
  487. //
  488. // Take the ansi string and convert it to unicode
  489. pwOutputFileBuf = (LPWSTR) MakeWideStrFromAnsi(iCodePage,(LPSTR) pInputFileBuf);
  490. if(NULL == pwOutputFileBuf)
  491. {
  492. _tprintf(_T("Out of memory\n"));
  493. goto Ansi2Unicode_Exit;
  494. }
  495. // Create a new unicode file
  496. hFile = CreateFile((LPCTSTR) szUnicodeFile_output, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  497. if( hFile == INVALID_HANDLE_VALUE)
  498. {
  499. _tprintf(_T("CreateFile:%s,error=0x%x\n"),szUnicodeFile_output,GetLastError());
  500. goto Ansi2Unicode_Exit;
  501. }
  502. // Write the BOF header to say that this is infact a unicode file
  503. bOneByte = 0xFF;
  504. WriteFile(hFile,(LPCVOID) &bOneByte, 1, &dwBytesWritten, NULL);
  505. bOneByte = 0xFE;
  506. WriteFile(hFile,(LPCVOID) &bOneByte, 1, &dwBytesWritten, NULL);
  507. // Append our data to the file
  508. if ( WriteFile( hFile, pwOutputFileBuf, wcslen(pwOutputFileBuf) * sizeof(WCHAR), &dwBytesWritten, NULL ) == FALSE )
  509. {
  510. _tprintf(_T("WriteFile:%s,error=%s\n"),szUnicodeFile_output,strerror(errno));
  511. goto Ansi2Unicode_Exit;
  512. }
  513. // SUCCESS
  514. iReturn = TRUE;
  515. Ansi2Unicode_Exit:
  516. if (INVALID_HANDLE_VALUE != hFile)
  517. {CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;}
  518. if (pInputFileBuf)
  519. {free(pInputFileBuf);pInputFileBuf=NULL;}
  520. if (pwOutputFileBuf)
  521. {GlobalFree(pwOutputFileBuf);pwOutputFileBuf=NULL;}
  522. return iReturn;
  523. }
  524. // returns 2 if the file is unicode
  525. // returns 1 if the file is not unicode
  526. // returns 0 on error
  527. int IsFileUnicode(TCHAR * szFile_input)
  528. {
  529. int iReturn = 0;
  530. HANDLE hFile = INVALID_HANDLE_VALUE;
  531. DWORD dwBytesToRead = 2;
  532. unsigned char *pInputFileBuf = NULL;
  533. DWORD dwBytesReadIn = 0;
  534. //
  535. // READ INPUT FILE
  536. //
  537. // open the input file with read access
  538. //
  539. hFile = CreateFile((LPCTSTR) szFile_input, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  540. if( hFile == INVALID_HANDLE_VALUE)
  541. {
  542. _tprintf(_T("Unable to open input file:%s,err=0x%x\n"),szFile_input,GetLastError());
  543. goto IsFileUnicode_Exit;
  544. }
  545. // allocate the memory the size of the file
  546. if ( ( pInputFileBuf = (unsigned char *) malloc( (size_t) dwBytesToRead) ) == NULL )
  547. {
  548. _tprintf(_T("Out of memory\n"));
  549. goto IsFileUnicode_Exit;
  550. }
  551. // clear buffer we just created
  552. memset(pInputFileBuf, 0, dwBytesToRead);
  553. // Read all the data from the file into the buffer
  554. if ( ReadFile( hFile, pInputFileBuf, dwBytesToRead, &dwBytesReadIn, NULL ) == FALSE )
  555. {
  556. _tprintf(_T("Readfile:%s, error=%s\n"),szFile_input,strerror(errno));
  557. goto IsFileUnicode_Exit;
  558. }
  559. // if the amount of data that we read in is different than
  560. // what the file size is then get out... we didn't read all of the data into the buffer.
  561. if (dwBytesToRead != dwBytesReadIn)
  562. {
  563. _tprintf(_T("Readfile:%s, error file too big to read into memory\n"),szFile_input);
  564. goto IsFileUnicode_Exit;
  565. }
  566. // check if the input file is unicode
  567. iReturn = 1;
  568. if (0xFF == pInputFileBuf[0] && 0xFE == pInputFileBuf[1])
  569. {
  570. iReturn = 2;
  571. }
  572. IsFileUnicode_Exit:
  573. if (INVALID_HANDLE_VALUE != hFile)
  574. {CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;}
  575. if (pInputFileBuf)
  576. {free(pInputFileBuf);pInputFileBuf=NULL;}
  577. return iReturn;
  578. }
  579. int StripControlZfromUnicodeFile(TCHAR * szFile_input,TCHAR * szFile_output)
  580. {
  581. // open the input file
  582. // if it's unicode, then see if it ends with a control Z
  583. int iReturn = 0;
  584. HANDLE hFile = INVALID_HANDLE_VALUE;
  585. DWORD dwFileSize = 0;
  586. unsigned char *pInputFileBuf = NULL;
  587. DWORD dwBytesReadIn = 0;
  588. int iFileIsUnicode = FALSE;
  589. int iWeNeedMakeChange = FALSE;
  590. //
  591. // READ INPUT FILE
  592. //
  593. // open the input file with read access
  594. //
  595. hFile = CreateFile((LPCTSTR) szFile_input, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  596. if( hFile == INVALID_HANDLE_VALUE)
  597. {
  598. _tprintf(_T("Unable to open input file:%s,err=0x%x\n"),szFile_input,GetLastError());
  599. goto StripControlZfromUnicodeFile_Exit;
  600. }
  601. // getfile size so we know how much memory we should allocate
  602. dwFileSize = GetFileSize(hFile, NULL);
  603. if (dwFileSize == 0)
  604. {
  605. _tprintf(_T("input file:%s is empty\n"),szFile_input);
  606. goto StripControlZfromUnicodeFile_Exit;
  607. }
  608. // allocate the memory the size of the file
  609. if ( ( pInputFileBuf = (unsigned char *) malloc( (size_t) dwFileSize + 1 ) ) == NULL )
  610. {
  611. _tprintf(_T("Out of memory\n"));
  612. goto StripControlZfromUnicodeFile_Exit;
  613. }
  614. // clear buffer we just created
  615. memset(pInputFileBuf, 0, dwFileSize + 1);
  616. // Read all the data from the file into the buffer
  617. if ( ReadFile( hFile, pInputFileBuf, dwFileSize, &dwBytesReadIn, NULL ) == FALSE )
  618. {
  619. _tprintf(_T("Readfile:%s, error=%s\n"),szFile_input,strerror(errno));
  620. goto StripControlZfromUnicodeFile_Exit;
  621. }
  622. // if the amount of data that we read in is different than
  623. // what the file size is then get out... we didn't read all of the data into the buffer.
  624. if (dwFileSize != dwBytesReadIn)
  625. {
  626. _tprintf(_T("Readfile:%s, error file too big to read into memory\n"),szFile_input);
  627. goto StripControlZfromUnicodeFile_Exit;
  628. }
  629. // check if the input file is unicode
  630. if (0xFF == pInputFileBuf[0] && 0xFE == pInputFileBuf[1])
  631. {
  632. iFileIsUnicode = TRUE;
  633. }
  634. // close the file we opened
  635. CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;
  636. // open file #2
  637. if (TRUE == iFileIsUnicode)
  638. {
  639. // Check if it has a control-z at the end
  640. if (0x1A == pInputFileBuf[dwFileSize])
  641. {
  642. pInputFileBuf[dwFileSize] = 0x0;
  643. iWeNeedMakeChange = TRUE;
  644. }
  645. if (0x1A == pInputFileBuf[dwFileSize-1])
  646. {
  647. pInputFileBuf[dwFileSize-1] = 0x0;
  648. iWeNeedMakeChange = TRUE;
  649. }
  650. }
  651. if (TRUE == iWeNeedMakeChange)
  652. {
  653. DWORD dwBytesWritten = 0;
  654. // Create a new unicode file
  655. hFile = CreateFile((LPCTSTR) szFile_output, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  656. if( hFile == INVALID_HANDLE_VALUE)
  657. {
  658. _tprintf(_T("CreateFile:%s,error=0x%x\n"),szFile_output,GetLastError());
  659. goto StripControlZfromUnicodeFile_Exit;
  660. }
  661. // write the file out that we fixed
  662. //
  663. // we have to minus out one byte here
  664. //
  665. // before:
  666. // 00 0D 00 0A 00 1A
  667. //
  668. // after
  669. // 00 0D 00 0A 00
  670. //
  671. if ( WriteFile( hFile, pInputFileBuf, dwBytesReadIn-1, &dwBytesWritten, NULL ) == FALSE )
  672. {
  673. _tprintf(_T("WriteFile:%s,error=%s\n"),szFile_output,strerror(errno));
  674. goto StripControlZfromUnicodeFile_Exit;
  675. }
  676. // return 1 to say that we had to strip of the control-z
  677. // from the end of the file
  678. iReturn = 1;
  679. }
  680. else
  681. {
  682. // just open the file over to the new filename
  683. if (FALSE == CopyFile((LPCTSTR)szFile_input,(LPCTSTR)szFile_output, FALSE))
  684. {
  685. _tprintf(_T("Failed to copy file %s to %s\n"),szFile_input,szFile_output);
  686. }
  687. }
  688. StripControlZfromUnicodeFile_Exit:
  689. if (INVALID_HANDLE_VALUE != hFile)
  690. {CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;}
  691. if (pInputFileBuf)
  692. {free(pInputFileBuf);pInputFileBuf=NULL;}
  693. return iReturn;
  694. }