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.

785 lines
23 KiB

  1. /*
  2. * sxspadfile.c - Routines for file i/o for sxspad
  3. * Copyright (C) 1984-2000 Microsoft Inc.
  4. */
  5. #include "precomp.h"
  6. HANDLE hFirstMem;
  7. CHAR BOM_UTF8[3]= {(BYTE) 0xEF, (BYTE) 0xBB, (BYTE)0xBF};
  8. //****************************************************************
  9. //
  10. // ReverseEndian
  11. //
  12. // Purpose: copies unicode character from one endian source
  13. // to another.
  14. //
  15. // may work on lpDst == lpSrc
  16. //
  17. VOID ReverseEndian( PTCHAR lpDst, PTCHAR lpSrc, DWORD nChars )
  18. {
  19. DWORD cnt;
  20. for( cnt=0; cnt < nChars; cnt++,lpDst++,lpSrc++ )
  21. {
  22. *lpDst= (TCHAR) (((*lpSrc<<8) & 0xFF00) + ((*lpSrc>>8)&0xFF));
  23. }
  24. }
  25. //*****************************************************************
  26. //
  27. // AnsiWriteFile()
  28. //
  29. // Purpose : To simulate the effects of _lwrite() in a Unicode
  30. // environment by converting to ANSI buffer and
  31. // writing out the ANSI text.
  32. // Returns : TRUE is successful, FALSE if not
  33. // GetLastError() will have the error code.
  34. //
  35. //*****************************************************************
  36. BOOL AnsiWriteFile(HANDLE hFile, // file to write to
  37. UINT uCodePage, // code page to convert unicode to
  38. LPVOID lpBuffer, // unicode buffer
  39. DWORD nChars, // number of unicode chars
  40. DWORD nBytes ) // number of ascii chars to produce
  41. {
  42. LPSTR lpAnsi; // pointer to allocate buffer
  43. BOOL Done; // status from write (returned)
  44. BOOL fDefCharUsed; // flag that conversion wasn't perfect
  45. BOOL* pfDefCharUsed; // pointer to flag
  46. DWORD nBytesWritten; // number of bytes written
  47. lpAnsi= (LPSTR) LocalAlloc( LPTR, nBytes + 1 );
  48. if( !lpAnsi )
  49. {
  50. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  51. return (FALSE);
  52. }
  53. pfDefCharUsed= NULL;
  54. if( (uCodePage != CP_UTF8 ) && (uCodePage != CP_UTF7) )
  55. {
  56. pfDefCharUsed= &fDefCharUsed;
  57. }
  58. WideCharToMultiByte( uCodePage, // code page
  59. 0, // performance and mapping flags
  60. (LPWSTR) lpBuffer,// wide char buffer
  61. nChars, // chars in wide char buffer
  62. lpAnsi, // resultant ascii string
  63. nBytes, // size of ascii string buffer
  64. NULL, // char to sub. for unmapped chars
  65. pfDefCharUsed); // flag to set if default char used
  66. Done= WriteFile( hFile, lpAnsi, nBytes, &nBytesWritten, NULL );
  67. LocalFree( lpAnsi );
  68. return (Done);
  69. } // end of AnsiWriteFile()
  70. #define NOTUSED 0
  71. static DWORD dwStartSel; // saved start of selection
  72. static DWORD dwEndSel; // saved end of selection
  73. VOID ClearFmt(VOID)
  74. {
  75. DWORD SelStart;
  76. DWORD SelEnd;
  77. SendMessage( hwndEdit, EM_GETSEL, (WPARAM) &dwStartSel, (LPARAM) &dwEndSel );
  78. SendMessage( hwndEdit, EM_SETSEL, (WPARAM) 0, (LPARAM) 0 ); // this is always legal
  79. // should we scrollcaret here?
  80. SendMessage( hwndEdit, EM_FMTLINES, (WPARAM)FALSE, NOTUSED ); // remove soft EOLs
  81. }
  82. VOID RestoreFmt(VOID)
  83. {
  84. UINT CharIndex;
  85. SendMessage( hwndEdit, EM_FMTLINES, (WPARAM)TRUE, NOTUSED ); // restore soft EOLS
  86. CharIndex= (UINT) SendMessage( hwndEdit, EM_SETSEL, (WPARAM) dwStartSel, (LPARAM) dwEndSel);
  87. }
  88. /* Save sxspad file to disk. szFileSave points to filename. fSaveAs
  89. is TRUE iff we are being called from SaveAsDlgProc. This implies we must
  90. open file on current directory, whether or not it already exists there
  91. or somewhere else in our search path.
  92. Assumes that text exists within hwndEdit. 30 July 1991 Clark Cyr
  93. */
  94. BOOL FAR SaveFile (HWND hwndParent, TCHAR *szFileSave, BOOL fSaveAs )
  95. {
  96. LPTSTR lpch;
  97. UINT nChars;
  98. BOOL flag;
  99. BOOL fNew = FALSE;
  100. BOOL fDefCharUsed = FALSE;
  101. BOOL* pfDefCharUsed;
  102. static WCHAR wchBOM = BYTE_ORDER_MARK;
  103. static WCHAR wchRBOM= REVERSE_BYTE_ORDER_MARK;
  104. HLOCAL hEText; // handle to MLE text
  105. DWORD nBytesWritten; // number of bytes written
  106. DWORD nAsciiLength; // length of equivalent ascii file
  107. UINT cpTemp= CP_ACP; // code page to convert to
  108. /* If saving to an existing file, make sure correct disk is in drive */
  109. if (!fSaveAs)
  110. {
  111. fp= CreateFile( szFileSave, // name of file
  112. GENERIC_READ|GENERIC_WRITE, // access mode
  113. FILE_SHARE_READ, // share mode
  114. NULL, // security descriptor
  115. OPEN_EXISTING, // how to create
  116. FILE_ATTRIBUTE_NORMAL, // file attributes
  117. NULL); // hnd of file with attrs
  118. }
  119. else
  120. {
  121. // Carefully open the file. Do not truncate it if it exists.
  122. // set the fNew flag if it had to be created.
  123. // We do all this in case of failures later in the process.
  124. fp= CreateFile( szFileSave, // name of file
  125. GENERIC_READ|GENERIC_WRITE, // access mode
  126. FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
  127. NULL, // security descriptor
  128. OPEN_ALWAYS, // how to create
  129. FILE_ATTRIBUTE_NORMAL, // file attributes
  130. NULL); // hnd of file with attrs
  131. if( fp != INVALID_HANDLE_VALUE )
  132. {
  133. fNew= (GetLastError() != ERROR_ALREADY_EXISTS );
  134. }
  135. }
  136. if( fp == INVALID_HANDLE_VALUE )
  137. {
  138. if (fSaveAs)
  139. AlertBox( hwndParent, szNN, szCREATEERR, szFileSave,
  140. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
  141. return FALSE;
  142. }
  143. // if wordwrap, remove soft carriage returns
  144. // Also move the cursor to a safe place to get around MLE bugs
  145. if( fWrap )
  146. {
  147. ClearFmt();
  148. }
  149. /* Must get text length after formatting */
  150. nChars = (UINT)SendMessage (hwndEdit, WM_GETTEXTLENGTH, 0, (LPARAM)0);
  151. hEText= (HANDLE) SendMessage( hwndEdit, EM_GETHANDLE, 0,0 );
  152. if( !hEText || !(lpch= (LPTSTR) LocalLock(hEText) ))
  153. {
  154. AlertUser_FileFail( szFileSave );
  155. goto CleanUp;
  156. }
  157. // Determine the SaveAs file type, and write the appropriate BOM.
  158. // If the filetype is UTF-8 or Ansi, do the conversion.
  159. switch(g_ftSaveAs)
  160. {
  161. case FT_UNICODE:
  162. WriteFile( fp, &wchBOM, ByteCountOf(1), &nBytesWritten, NULL );
  163. flag= WriteFile(fp, lpch, ByteCountOf(nChars), &nBytesWritten, NULL);
  164. break;
  165. case FT_UNICODEBE:
  166. WriteFile( fp, &wchRBOM, ByteCountOf(1), &nBytesWritten, NULL );
  167. ReverseEndian( lpch, lpch,nChars );
  168. flag= WriteFile(fp, lpch, ByteCountOf(nChars), &nBytesWritten, NULL);
  169. ReverseEndian( lpch, lpch, nChars );
  170. break;
  171. // If it UTF-8, write the BOM (3 bytes), set the code page and fall
  172. // through to the default case.
  173. case FT_UTF8:
  174. WriteFile( fp, &BOM_UTF8, 3, &nBytesWritten, NULL );
  175. cpTemp= CP_UTF8;
  176. // fall through to convert and write the file
  177. default:
  178. pfDefCharUsed= NULL;
  179. if (g_ftSaveAs != FT_UTF8)
  180. {
  181. //
  182. // Always use the current locale code page to do the translation
  183. // If the user changes locales, they will need to know what locale
  184. // this version of the file was saved with. Since we don't save that
  185. // information, the user may be backed into a corner. Unicode would
  186. // save his bacon.
  187. //
  188. cpTemp= GetACP();
  189. pfDefCharUsed= &fDefCharUsed;
  190. }
  191. nAsciiLength= WideCharToMultiByte( cpTemp,
  192. 0,
  193. (LPWSTR)lpch,
  194. nChars,
  195. NULL,
  196. 0,
  197. NULL,
  198. pfDefCharUsed);
  199. if( fDefCharUsed )
  200. {
  201. if ( AlertBox( hwndParent, szNN, szErrUnicode, szFileSave,
  202. MB_APPLMODAL|MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
  203. goto CleanUp;
  204. }
  205. flag= AnsiWriteFile( fp, cpTemp, lpch, nChars, nAsciiLength );
  206. break;
  207. }
  208. if (!flag)
  209. {
  210. SetCursor(hStdCursor); /* display normal cursor */
  211. AlertUser_FileFail( szFileSave );
  212. CleanUp:
  213. SetCursor( hStdCursor );
  214. CloseHandle (fp); fp=INVALID_HANDLE_VALUE;
  215. if( hEText )
  216. LocalUnlock( hEText );
  217. if (fNew)
  218. DeleteFile (szFileSave);
  219. /* if wordwrap, insert soft carriage returns */
  220. if (fWrap)
  221. {
  222. RestoreFmt();
  223. }
  224. return FALSE;
  225. }
  226. else
  227. {
  228. SetEndOfFile (fp);
  229. SendMessage (hwndEdit, EM_SETMODIFY, FALSE, 0L);
  230. SetTitle (szFileSave);
  231. fUntitled = FALSE;
  232. }
  233. CloseHandle (fp); fp=INVALID_HANDLE_VALUE;
  234. if( hEText )
  235. LocalUnlock( hEText );
  236. /* if wordwrap, insert soft carriage returns */
  237. if (fWrap)
  238. {
  239. RestoreFmt();
  240. }
  241. /* Display the hour glass cursor */
  242. SetCursor(hStdCursor);
  243. return TRUE;
  244. } // end of SaveFile()
  245. /* Read contents of file from disk.
  246. * Do any conversions required.
  247. * File is already open, referenced by handle fp
  248. * Close the file when done.
  249. * If typeFlag>=0, then use it as filetype, otherwise do automagic guessing.
  250. */
  251. BOOL FAR LoadFile (TCHAR * sz, INT typeFlag )
  252. {
  253. UINT len, i, nChars;
  254. LPTSTR lpch=NULL;
  255. LPTSTR lpBuf;
  256. LPSTR lpBufAfterBOM;
  257. BOOL fLog=FALSE;
  258. TCHAR* p;
  259. TCHAR szSave[MAX_PATH]; /* Private copy of current filename */
  260. BOOL bUnicode=FALSE; /* true if file detected as unicode */
  261. BOOL bUTF8=FALSE; /* true if file detected as UTF-8 */
  262. DWORD nBytesRead; // number of bytes read
  263. BY_HANDLE_FILE_INFORMATION fiFileInfo;
  264. BOOL bStatus; // boolean status
  265. HLOCAL hNewEdit=NULL; // new handle for edit buffer
  266. HANDLE hMap; // file mapping handle
  267. TCHAR szNullFile[2]; // fake null mapped file
  268. INT cpTemp = CP_ACP;
  269. SP_FILETYPE ftOpenedAs=FT_UNKNOWN;
  270. if( fp == INVALID_HANDLE_VALUE )
  271. {
  272. AlertUser_FileFail( sz );
  273. return (FALSE);
  274. }
  275. //
  276. // Get size of file
  277. // We use this heavy duty GetFileInformationByHandle API
  278. // because it finds bugs. It takes longer, but it only is
  279. // called at user interaction time.
  280. //
  281. bStatus= GetFileInformationByHandle( fp, &fiFileInfo );
  282. len= (UINT) fiFileInfo.nFileSizeLow;
  283. // NT may delay giving this status until the file is accessed.
  284. // i.e. the open succeeds, but operations may fail on damaged files.
  285. if( !bStatus )
  286. {
  287. AlertUser_FileFail( sz );
  288. CloseHandle( fp ); fp=INVALID_HANDLE_VALUE;
  289. return( FALSE );
  290. }
  291. // If the file is too big, fail now.
  292. // -1 not valid because we need a zero on the end.
  293. if( len == -1 || fiFileInfo.nFileSizeHigh != 0 )
  294. {
  295. AlertBox( hwndSP, szNN, szErrSpace, sz,
  296. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
  297. CloseHandle (fp); fp=INVALID_HANDLE_VALUE;
  298. return (FALSE);
  299. }
  300. SetCursor(hWaitCursor); // physical I/O takes time
  301. //
  302. // Create a file mapping so we don't page the file to
  303. // the pagefile. This is a big win on small ram machines.
  304. //
  305. if( len != 0 )
  306. {
  307. lpBuf= NULL;
  308. hMap= CreateFileMapping( fp, NULL, PAGE_READONLY, 0, len, NULL );
  309. if( hMap )
  310. {
  311. lpBuf= MapViewOfFile( hMap, FILE_MAP_READ, 0,0,len);
  312. CloseHandle( hMap );
  313. }
  314. }
  315. else // file mapping doesn't work on zero length files
  316. {
  317. lpBuf= (LPTSTR) &szNullFile;
  318. *lpBuf= 0; // null terminate
  319. }
  320. CloseHandle( fp ); fp=INVALID_HANDLE_VALUE;
  321. if( lpBuf == NULL )
  322. {
  323. SetCursor( hStdCursor );
  324. AlertBox( hwndSP, szNN, szErrSpace, sz,
  325. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
  326. return( FALSE );
  327. }
  328. //
  329. // protect access to the mapped file with a try/except so we
  330. // can detect I/O errors.
  331. //
  332. //
  333. // WARNING: be very very careful. This code is pretty fragile.
  334. // Files across the network, or RSM files (tape) may throw excepts
  335. // at random points in this code. Anywhere the code touches the
  336. // memory mapped file can cause an AV. Make sure variables are
  337. // in consistent state if an exception is thrown. Be very careful
  338. // with globals.
  339. __try
  340. {
  341. /* Determine the file type and number of characters
  342. * If the user overrides, use what is specified.
  343. * Otherwise, we depend on 'IsTextUnicode' getting it right.
  344. * If it doesn't, bug IsTextUnicode.
  345. */
  346. lpBufAfterBOM= (LPSTR) lpBuf;
  347. if( typeFlag == FT_UNKNOWN )
  348. {
  349. switch(*lpBuf)
  350. {
  351. case BYTE_ORDER_MARK:
  352. bUnicode= TRUE;
  353. ftOpenedAs= FT_UNICODE;
  354. // don't count the BOM.
  355. nChars= len / sizeof(TCHAR) -1;
  356. break;
  357. case REVERSE_BYTE_ORDER_MARK:
  358. bUnicode= TRUE;
  359. ftOpenedAs= FT_UNICODEBE;
  360. // don't count the BOM.
  361. nChars= len / sizeof(TCHAR) -1;
  362. break;
  363. // UTF bom has 3 bytes; if it doesn't have UTF BOM just fall through ..
  364. case BOM_UTF8_HALF:
  365. if (len > 2 && ((BYTE) *(((LPSTR)lpBuf)+2) == BOM_UTF8_2HALF) )
  366. {
  367. bUTF8= TRUE;
  368. cpTemp= CP_UTF8;
  369. ftOpenedAs= FT_UTF8;
  370. // Ignore the first three bytes.
  371. lpBufAfterBOM= (LPSTR)lpBuf + 3;
  372. len -= 3;
  373. break;
  374. }
  375. default:
  376. // Is the file unicode without BOM ?
  377. if ((bUnicode= IsInputTextUnicode((LPSTR) lpBuf, len)))
  378. {
  379. ftOpenedAs= FT_UNICODE;
  380. nChars= len / sizeof(TCHAR);
  381. }
  382. else
  383. {
  384. // Is the file UTF-8 even though it doesn't have UTF-8 BOM.
  385. if ((bUTF8= IsTextUTF8((LPSTR) lpBuf, len)))
  386. {
  387. ftOpenedAs= FT_UTF8;
  388. cpTemp= CP_UTF8;
  389. }
  390. // well, not it must be an ansi file!
  391. else
  392. {
  393. ftOpenedAs= FT_ANSI;
  394. cpTemp= CP_ACP;
  395. }
  396. }
  397. break;
  398. }
  399. }
  400. // find out no. of chars present in the string.
  401. if (!bUnicode)
  402. {
  403. nChars = MultiByteToWideChar (cpTemp,
  404. 0,
  405. (LPSTR)lpBufAfterBOM,
  406. len,
  407. NULL,
  408. 0);
  409. }
  410. //
  411. // Don't display text until all done.
  412. //
  413. SendMessage (hwndEdit, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM)0);
  414. // Reset selection to 0
  415. SendMessage(hwndEdit, EM_SETSEL, 0, 0L);
  416. SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
  417. // resize the edit buffer
  418. // if we can't resize the memory, inform the user
  419. if (!(hNewEdit= LocalReAlloc(hEdit,ByteCountOf(nChars + 1),LMEM_MOVEABLE)))
  420. {
  421. /* Bug 7441: New() causes szFileName to be set to "Untitled". Save a
  422. * copy of the filename to pass to AlertBox.
  423. * 17 November 1991 Clark R. Cyr
  424. */
  425. lstrcpy(szSave, sz);
  426. New(FALSE);
  427. /* Display the hour glass cursor */
  428. SetCursor(hStdCursor);
  429. AlertBox( hwndSP, szNN, szFTL, szSave,
  430. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
  431. if( lpBuf != (LPTSTR) &szNullFile )
  432. {
  433. UnmapViewOfFile( lpBuf );
  434. }
  435. // let user see old text
  436. SendMessage (hwndEdit, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM)0);
  437. return FALSE;
  438. }
  439. /* Transfer file from temporary buffer to the edit buffer */
  440. lpch= (LPTSTR) LocalLock(hNewEdit);
  441. if( bUnicode )
  442. {
  443. /* skip the Byte Order Mark */
  444. if (*lpBuf == BYTE_ORDER_MARK)
  445. {
  446. CopyMemory (lpch, lpBuf + 1, ByteCountOf(nChars));
  447. }
  448. else if( *lpBuf == REVERSE_BYTE_ORDER_MARK )
  449. {
  450. ReverseEndian( lpch, lpBuf+1, nChars );
  451. }
  452. else
  453. {
  454. CopyMemory (lpch, lpBuf, ByteCountOf(nChars));
  455. }
  456. }
  457. else
  458. {
  459. nChars = MultiByteToWideChar (cpTemp,
  460. 0,
  461. (LPSTR)lpBufAfterBOM,
  462. len,
  463. (LPWSTR)lpch,
  464. nChars);
  465. }
  466. g_ftOpenedAs= ftOpenedAs; // got everything; update global safe now
  467. }
  468. __except(EXCEPTION_EXECUTE_HANDLER)
  469. {
  470. AlertBox( hwndSP, szNN, szDiskError, sz,
  471. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
  472. nChars= 0; // don't deal with it.
  473. }
  474. /* Free file mapping */
  475. if( lpBuf != (LPTSTR) &szNullFile )
  476. {
  477. UnmapViewOfFile( lpBuf );
  478. }
  479. if( lpch )
  480. {
  481. // Fix any NUL character that came in from the file to be spaces.
  482. for (i = 0, p = lpch; i < nChars; i++, p++)
  483. {
  484. if( *p == (TCHAR) 0 )
  485. *p= TEXT(' ');
  486. }
  487. // null terminate it. Safe even if nChars==0 because it is 1 TCHAR bigger
  488. *(lpch+nChars)= (TCHAR) 0; /* zero terminate the thing */
  489. // Set 'fLog' if first characters in file are ".LOG"
  490. fLog= *lpch++ == TEXT('.') && *lpch++ == TEXT('L') &&
  491. *lpch++ == TEXT('O') && *lpch == TEXT('G');
  492. }
  493. if( hNewEdit )
  494. {
  495. LocalUnlock( hNewEdit );
  496. // now it is safe to set the global edit handle
  497. hEdit= hNewEdit;
  498. }
  499. lstrcpy( szFileName, sz );
  500. SetTitle( sz );
  501. fUntitled= FALSE;
  502. /* Pass handle to edit control. This is more efficient than WM_SETTEXT
  503. * which would require twice the buffer space.
  504. */
  505. /* Bug 7443: If EM_SETHANDLE doesn't have enough memory to complete things,
  506. * it will send the EN_ERRSPACE message. If this happens, don't put up the
  507. * out of memory notification, put up the file to large message instead.
  508. * 17 November 1991 Clark R. Cyr
  509. */
  510. dwEmSetHandle = SETHANDLEINPROGRESS;
  511. SendMessage (hwndEdit, EM_SETHANDLE, (WPARAM)hEdit, (LPARAM)0);
  512. if (dwEmSetHandle == SETHANDLEFAILED)
  513. {
  514. SetCursor(hStdCursor);
  515. dwEmSetHandle = 0;
  516. AlertBox( hwndSP, szNN, szFTL, sz,MB_APPLMODAL|MB_OK|MB_ICONEXCLAMATION);
  517. New (FALSE);
  518. SendMessage (hwndEdit, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM)0);
  519. return (FALSE);
  520. }
  521. dwEmSetHandle = 0;
  522. PostMessage (hwndEdit, EM_LIMITTEXT, (WPARAM)CCHSPMAX, 0L);
  523. /* If file starts with ".LOG" go to end and stamp date time */
  524. if (fLog)
  525. {
  526. SendMessage( hwndEdit, EM_SETSEL, (WPARAM)nChars, (LPARAM)nChars);
  527. SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0);
  528. InsertDateTime(TRUE);
  529. }
  530. /* Move vertical thumb to correct position */
  531. SetScrollPos (hwndSP,
  532. SB_VERT,
  533. (int) SendMessage (hwndEdit, WM_VSCROLL, EM_GETTHUMB, 0L),
  534. TRUE);
  535. /* Now display text */
  536. SendMessage( hwndEdit, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM)0 );
  537. InvalidateRect( hwndEdit, (LPRECT)NULL, TRUE );
  538. UpdateWindow( hwndEdit );
  539. SetCursor(hStdCursor);
  540. return( TRUE );
  541. } // end of LoadFile()
  542. /* New Command - reset everything
  543. */
  544. void FAR New (BOOL fCheck)
  545. {
  546. HANDLE hTemp;
  547. TCHAR* pSz;
  548. if (!fCheck || CheckSave (FALSE))
  549. {
  550. SendMessage( hwndEdit, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("") );
  551. fUntitled= TRUE;
  552. lstrcpy( szFileName, szUntitled );
  553. SetTitle(szFileName );
  554. SendMessage( hwndEdit, EM_SETSEL, 0, 0L );
  555. SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0 );
  556. // resize of 1 NULL character i.e. zero length
  557. hTemp= LocalReAlloc( hEdit, sizeof(TCHAR), LMEM_MOVEABLE );
  558. if( hTemp )
  559. {
  560. hEdit= hTemp;
  561. }
  562. // null terminate the buffer. LocalReAlloc won't do it
  563. // because in all cases it is not growing which is the
  564. // only time it would zero out anything.
  565. pSz= LocalLock( hEdit );
  566. *pSz= TEXT('\0');
  567. LocalUnlock( hEdit );
  568. SendMessage (hwndEdit, EM_SETHANDLE, (WPARAM)hEdit, 0L);
  569. szSearch[0] = (TCHAR) 0;
  570. }
  571. } // end of New()
  572. /* If sz does not have extension, append ".Manifest"
  573. * This function is useful for getting to undecorated filenames
  574. * that setup apps use. DO NOT CHANGE the extension. Too many setup
  575. * apps depend on this functionality.
  576. */
  577. void FAR AddExt( TCHAR* sz )
  578. {
  579. TCHAR* pch1;
  580. int ch;
  581. DWORD dwSize;
  582. dwSize= lstrlen(sz);
  583. pch1= sz + dwSize; // point to end
  584. ch= *pch1;
  585. while( ch != TEXT('.') && ch != TEXT('\\') && ch != TEXT(':') && pch1 > sz)
  586. {
  587. //
  588. // backup one character. Do NOT use CharPrev because
  589. // it sometimes doesn't actually backup. Some Thai
  590. // tone marks fit this category but there seems to be others.
  591. // This is safe since it will stop at the beginning of the
  592. // string or on delimiters listed above. bug# 139374 2/13/98
  593. //
  594. // pch1= (TCHAR*)CharPrev (sz, pch1);
  595. pch1--; // back up
  596. ch= *pch1;
  597. }
  598. if( *pch1 != TEXT('.') )
  599. {
  600. if( dwSize + sizeof(".Manifest") <= MAX_PATH ) { // avoid buffer overruns
  601. lstrcat( sz, TEXT(".Manifest") );
  602. }
  603. }
  604. }
  605. /* AlertUser_FileFail( LPTSTR szFileName )
  606. *
  607. * szFileName is the name of file that was attempted to open.
  608. * Some sort of failure on file open. Alert the user
  609. * with some monologue box. At least give him decent
  610. * error messages.
  611. */
  612. VOID FAR AlertUser_FileFail( LPTSTR szFileName )
  613. {
  614. TCHAR msg[256]; // buffer to format message into
  615. DWORD dwStatus; // status from FormatMessage
  616. UINT style= MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION;
  617. // Check GetLastError to see why we failed
  618. dwStatus=
  619. FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS |
  620. FORMAT_MESSAGE_FROM_SYSTEM,
  621. NULL,
  622. GetLastError(),
  623. GetUserDefaultLangID(),
  624. msg, // where message will end up
  625. CharSizeOf(msg), NULL );
  626. if( dwStatus )
  627. {
  628. MessageBox( hwndSP, msg, szNN, style );
  629. }
  630. else
  631. {
  632. AlertBox( hwndSP, szNN, szDiskError, szFileName, style );
  633. }
  634. }