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.

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