home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / porttool / ptbkport.c < prev    next >
C/C++ Source or Header  |  1996-06-12  |  14KB  |  508 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-96 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. #include "porttool.h"
  13. #include "port.h"
  14.  
  15.  
  16. /* define line types returned from GetNextLine */
  17. #define VALID_LINE     0
  18. #define COMMENT_LINE     1
  19. #define EOF_LINE     2
  20.  
  21. #define CARRIAGE_RETURN  13
  22. #define LINE_FEED     10
  23.  
  24. /* define worker functions for this module */
  25. int  WINAPI GetNextLine (char *, int, char *, char *, BOOL *);
  26. int  WINAPI NextLineLength (char *, char *, int);
  27. BOOL WINAPI BkFilePortThread (LPBKPORTFILESTRUCT);
  28. void WINAPI DateTimeStamp (char *);
  29.  
  30.  
  31.  
  32. /* function creates a background porting thread */
  33. HANDLE WINAPI StartBkPortThread (LPBKPORTFILESTRUCT    lpBkPort)
  34. {
  35.     DWORD    id;
  36.  
  37.     /* create thread with initial structure */
  38.     return (lpBkPort->hThread = CreateThread ((LPSECURITY_ATTRIBUTES)NULL,
  39.                       4096,
  40.                       (LPTHREAD_START_ROUTINE)BkFilePortThread,
  41.                       (LPVOID)lpBkPort,
  42.                       0,
  43.                       &id));
  44. }
  45.  
  46.  
  47. /* independent thread function that performs background file porting */
  48. BOOL WINAPI BkFilePortThread (
  49.     LPBKPORTFILESTRUCT      lpBkPort)
  50. {
  51.     HANDLE    hEvents[nBKPORTEVENTS];
  52.     HANDLE    hFile;
  53.     OFSTRUCT    of;
  54.     DWORD    nFileSize;
  55.     DWORD       nBytes;
  56.     HANDLE    hFileBuffer;
  57.     char    *lpFile, *lpFilePtr;
  58.     WORD    wComplete, wIssues = 0;
  59.     int     nLines = 0;
  60.     BOOL    bCommentOn;
  61.     HANDLE    hLine;
  62.     HANDLE    hToken, hIssue, hSuggest, hHelp;
  63.     RESULT    rIssue;
  64.     char    *lpLine;
  65.     char    szHeader[MAX_PATH], szToken[50], szIssue[50], szdt[50],
  66.         szSuggest[50], szHelp[50], szHelpFile[50], szEOL[50], szNL[5];
  67.  
  68.  
  69.     /* adjust our priority to below normal */
  70.     SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_BELOW_NORMAL);
  71.  
  72.     /* attach our thread input to the parent thread so we can post messages directly */
  73.     AttachThreadInput (GetCurrentThreadId (),
  74.                GetWindowThreadProcessId (lpBkPort->hDlg, NULL),
  75.                TRUE);
  76.  
  77.     /* load file comment strings */
  78.     LoadString (GetModuleHandle (NULL), IDS_BKPORTNEWLINE, szNL, 5);
  79.     LoadString (GetModuleHandle (NULL), IDS_BKPORTHEADER, szHeader, MAX_PATH);
  80.     LoadString (GetModuleHandle (NULL), IDS_BKPORTTOKEN, szToken, 50);
  81.     LoadString (GetModuleHandle (NULL), IDS_BKPORTISSUE, szIssue, 50);
  82.     LoadString (GetModuleHandle (NULL), IDS_BKPORTSUGGEST, szSuggest, 50);
  83.     LoadString (GetModuleHandle (NULL), IDS_BKPORTHELP, szHelp, 50);
  84.     LoadString (GetModuleHandle (NULL), IDS_BKPORTHELPFILE, szHelpFile, 50);
  85.     LoadString (GetModuleHandle (NULL), IDS_BKPORTEOL, szEOL, 50);
  86.  
  87.     /* initialize wait events for communication between threads */
  88.     if (!CreateEvents (hEvents, lpBkPort))
  89.     return FALSE;
  90.  
  91.     /* open file for porting and read into buffer */
  92.     if ((int)(hFile = (HANDLE)OpenFile (lpBkPort->szFilePath, &of, OF_READWRITE)) == -1)
  93.     {
  94.     DestroyEvents (hEvents);
  95.     return FALSE;
  96.     }
  97.  
  98.     /* global allocate buffer for file */
  99.     if (!(hFileBuffer = GlobalAlloc (GPTR, (nFileSize = GetFileSize (hFile, NULL))+1)) ||
  100.     !(lpFile = (char *)GlobalLock (hFileBuffer)))
  101.     {
  102.     CloseHandle (hFile);
  103.     DestroyEvents (hEvents);
  104.     return FALSE;
  105.     }
  106.  
  107.     /* allocate initial line buffer of reasonable size */
  108.     hLine = GlobalAlloc (GMEM_MOVEABLE, 1024);
  109.  
  110.     /* allocate local memory segments for porttool RESULT strings */
  111.     if (!(rIssue.lpszToken = LocalLock (hToken = LocalAlloc (LHND, MAXTOKENLEN))) ||
  112.     !(rIssue.lpszHelpStr = LocalLock (hHelp = LocalAlloc (LHND, MAXHELPLEN))) ||
  113.     !(rIssue.lpszIssue = LocalLock (hIssue = LocalAlloc (LHND, MAXISSUELEN))) ||
  114.     !(rIssue.lpszSuggest = LocalLock (hSuggest = LocalAlloc (LHND, MAXSUGGESTLEN))))
  115.     {
  116.     CloseHandle (hFile);
  117.     GlobalUnlock (lpFile);
  118.     GlobalFree (hFileBuffer);
  119.     DestroyEvents (hEvents);
  120.     GlobalFree (hLine);
  121.     return FALSE;
  122.     }
  123.  
  124.     /* read entire file into buffer and zero terminate */
  125.     ReadFile (hFile, lpFile, nFileSize, &nBytes, NULL);
  126.     lpFile[nFileSize] = 0;
  127.     lpFilePtr = lpFile;
  128.  
  129.     /* if bytes read not equal to size of file, abort */
  130.     if (nBytes != nFileSize)
  131.     {
  132.     CloseHandle (hFile);
  133.     GlobalUnlock (lpFile);
  134.     GlobalFree (hFileBuffer);
  135.     DestroyEvents (hEvents);
  136.     GlobalFree (hLine);
  137.     return FALSE;
  138.     }
  139.  
  140.     /* reset file to size zero before beginning porting */
  141.     SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
  142.     SetEndOfFile (hFile);
  143.     WriteFile (hFile, szHeader, strlen (szHeader), &nBytes, NULL);
  144.     WriteFile (hFile, lpBkPort->szFile, strlen (lpBkPort->szFile), &nBytes, NULL);
  145.     WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  146.     WriteFile (hFile, szNL, strlen (szNL), &nBytes, NULL);
  147.  
  148.     while (TRUE)
  149.     {
  150.     /* wait 1ms for either abort or status events to signal */
  151.     switch (WaitForMultipleObjects (nBKPORTEVENTS, hEvents, FALSE, 1))
  152.         {
  153.         case BKPORT_ABORT:
  154.         {
  155.         char    szAbort[MAX_PATH];
  156.  
  157.         /* create time and date */
  158.         DateTimeStamp (szdt);
  159.  
  160.         /* write header line */
  161.         WriteFile (hFile, szHeader, strlen (szHeader), &nBytes, NULL);
  162.         WriteFile (hFile, szdt, strlen (szdt), &nBytes, NULL);
  163.         WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  164.         WriteFile (hFile, szNL, strlen (szNL), &nBytes, NULL);
  165.  
  166.         /* load abort string and write to file */
  167.         LoadString (GetModuleHandle (NULL),
  168.                 IDS_BKPORTABORT,
  169.                 szAbort,
  170.                 MAX_PATH);
  171.         WriteFile (hFile, szAbort, strlen (szAbort), (LPDWORD)&nBytes, NULL);
  172.  
  173.         /* write rest of file to disk */
  174.         WriteFile (hFile,
  175.                (VOID *)lpFilePtr,
  176.                (nFileSize - (lpFilePtr-lpFile)),
  177.                (LPDWORD)&nBytes,
  178.                NULL);
  179.  
  180.         /* clean up */
  181.         CloseHandle (hFile);
  182.         GlobalUnlock (lpFile);
  183.         GlobalFree (hFileBuffer);
  184.         GlobalFree (hLine);
  185.         DestroyEvents (hEvents);
  186.  
  187.         /* free RESULT strings */
  188.         LocalUnlock (hToken); LocalFree (hToken);
  189.         LocalUnlock (hHelp); LocalFree (hHelp);
  190.         LocalUnlock (hIssue); LocalFree (hIssue);
  191.         LocalUnlock (hSuggest); LocalFree (hSuggest);
  192.  
  193.         /* exit thread */
  194.         return FALSE;
  195.         }
  196.         break;
  197.  
  198.         case BKPORT_STATUS:
  199.         /* post message to parent thread with status info */
  200.         PostMessage (lpBkPort->hDlg,
  201.                  UM_STATUSUPDATE,
  202.                  MAKELONG (wIssues, wComplete),
  203.                  nLines);
  204.         break;
  205.  
  206.         case WAIT_TIMEOUT:
  207.         /* if we timed out ignore */
  208.         break;
  209.  
  210.         default:
  211.         /* anything else is an error */
  212.         ErrorNotify (lpBkPort->hDlg, GetLastError ());
  213.         goto DONE;
  214.         break;
  215.         }
  216.  
  217.     /* reset line buffer */
  218.     GlobalReAlloc (hLine,
  219.                NextLineLength (lpFilePtr, lpFile, nFileSize),
  220.                GMEM_MOVEABLE);
  221.     lpLine = (char *)GlobalLock (hLine);
  222.     *lpLine = 0;
  223.  
  224.     /* get next line from  file buffer */
  225.     switch (GetNextLine (lpFile, nFileSize, lpFilePtr, lpLine, &bCommentOn))
  226.         {
  227.         /* check valid strings for porting issues */
  228.         case VALID_LINE:
  229.         /* initialize rIssue string lengths */
  230.         *(WORD *)rIssue.lpszToken = MAXTOKENLEN;
  231.         *(WORD *)rIssue.lpszHelpStr = MAXHELPLEN;
  232.         *(WORD *)rIssue.lpszIssue = MAXISSUELEN;
  233.         *(WORD *)rIssue.lpszSuggest = MAXSUGGESTLEN;
  234.  
  235.         if (CheckString (lpLine, lpBkPort->dwPTFlags, &rIssue))
  236.             {
  237.             /* create time and date */
  238.             DateTimeStamp (szdt);
  239.  
  240.             /* write header line */
  241.             WriteFile (hFile, szNL, strlen (szNL), &nBytes, NULL);
  242.             WriteFile (hFile, szHeader, strlen (szHeader), &nBytes, NULL);
  243.             WriteFile (hFile, szdt, strlen (szdt), &nBytes, NULL);
  244.             WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  245.  
  246.             /* write token line */
  247.             WriteFile (hFile, szToken, strlen (szToken), &nBytes, NULL);
  248.             WriteFile (hFile,
  249.                    rIssue.lpszToken,
  250.                    strlen (rIssue.lpszToken),
  251.                    &nBytes,
  252.                    NULL);
  253.             WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  254.  
  255.             /* write issue line */
  256.             WriteFile (hFile, szIssue, strlen (szIssue), &nBytes, NULL);
  257.             WriteFile (hFile,
  258.                    rIssue.lpszIssue,
  259.                    strlen (rIssue.lpszIssue),
  260.                    &nBytes,
  261.                    NULL);
  262.             WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  263.  
  264.             /* if suggestion */
  265.             if (*(rIssue.lpszSuggest))
  266.             {
  267.             WriteFile (hFile, szSuggest, strlen (szSuggest), &nBytes, NULL);
  268.             WriteFile (hFile,
  269.                    rIssue.lpszSuggest,
  270.                    strlen (rIssue.lpszSuggest),
  271.                    &nBytes,
  272.                    NULL);
  273.             WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  274.             }
  275.  
  276.             /* if help string */
  277.             if (*(rIssue.lpszSuggest))
  278.             {
  279.             WriteFile (hFile, szHelp, strlen (szHelp), &nBytes, NULL);
  280.             WriteFile (hFile,
  281.                    rIssue.lpszHelpStr,
  282.                    strlen (rIssue.lpszHelpStr),
  283.                    &nBytes,
  284.                    NULL);
  285.             WriteFile (hFile, szHelpFile, strlen (szHelpFile), &nBytes, NULL);
  286.             WriteFile (hFile, szEOL, strlen (szEOL), &nBytes, NULL);
  287.             }
  288.  
  289.             wIssues++;
  290.             }
  291.  
  292.         case COMMENT_LINE:
  293.         /* write line to file whether comment or not */
  294.         WriteFile (hFile, lpLine, strlen (lpLine), &nBytes, NULL);
  295.         break;
  296.  
  297.         case EOF_LINE:
  298.         if (*lpLine)
  299.             WriteFile (hFile, lpLine, strlen (lpLine), &nBytes, NULL);
  300.         goto DONE;
  301.         break;
  302.         }
  303.  
  304.     /* unlock line buffer */
  305.     GlobalUnlock (hLine);
  306.  
  307.     /* update status counts */
  308.     lpFilePtr += strlen (lpLine);
  309.     nLines++;
  310.     wComplete = (WORD)(((lpFilePtr-lpFile)*100)/nFileSize);
  311.     }
  312.  
  313. DONE:
  314.     /* clean up */
  315.     CloseHandle (hFile);
  316.     GlobalUnlock (lpFile);
  317.     GlobalFree (hFileBuffer);
  318.     GlobalFree (hLine);
  319.     DestroyEvents (hEvents);
  320.  
  321.     /* free RESULT strings */
  322.     LocalUnlock (hToken); LocalFree (hToken);
  323.     LocalUnlock (hHelp); LocalFree (hHelp);
  324.     LocalUnlock (hIssue); LocalFree (hIssue);
  325.     LocalUnlock (hSuggest); LocalFree (hSuggest);
  326.  
  327.     /* send message to parent that thread is dead */
  328.     PostMessage (lpBkPort->hDlg,
  329.          UM_THREADCOMPLETE,
  330.          (WPARAM)lpBkPort->hThread,
  331.          0);
  332.  
  333.     /* exit thread */
  334.     return TRUE;
  335. }
  336.  
  337.  
  338.  
  339. void WINAPI DateTimeStamp (
  340.     char    *lpszDT)
  341. {
  342.     SYSTEMTIME      dt;
  343.     char      Buff[10];
  344.  
  345.     /* create time and date stamp */
  346.     GetSystemTime (&dt);
  347.  
  348.     //
  349.     // On Japanese system change the date display order,
  350.     //  we should do this right w/ locales eventually.
  351.     //
  352.     if (PRIMARYLANGID(GetUserDefaultLangID ()) == LANG_JAPANESE) {
  353.  
  354.       strcpy (lpszDT, itoa (dt.wYear, Buff, 10));
  355.       strcat (lpszDT, "/");
  356.       strcat (lpszDT, itoa (dt.wMonth, Buff, 10));
  357.       strcat (lpszDT, "/");
  358.       strcat (lpszDT, itoa (dt.wDay, Buff, 10));
  359.     } else {
  360.       strcpy (lpszDT, itoa (dt.wMonth, Buff, 10));
  361.       strcat (lpszDT, "/");
  362.       strcat (lpszDT, itoa (dt.wDay, Buff, 10));
  363.       strcat (lpszDT, "/");
  364.       strcat (lpszDT, itoa (dt.wYear, Buff, 10));
  365.     }
  366.  
  367.     strcat (lpszDT, "    ");
  368.     strcat (lpszDT, itoa (dt.wHour, Buff, 10));
  369.     strcat (lpszDT, ":");
  370.     strcat (lpszDT, itoa (dt.wMinute, Buff, 10));
  371. }
  372.  
  373.  
  374.  
  375.  
  376.  
  377. BOOL WINAPI CreateEvents (
  378.     HANDLE          *lphEvents,
  379.     LPBKPORTFILESTRUCT      lpBkPort)
  380. {
  381.     char    szEvent[MAX_PATH];
  382.  
  383.  
  384.     LoadString (GetModuleHandle (NULL), IDS_BKPORTABORT, szEvent, MAX_PATH);
  385.     strcat (szEvent, lpBkPort->szFile);
  386.     if (!(lphEvents[BKPORT_ABORT] = CreateEvent (NULL, TRUE, FALSE, szEvent)))
  387.     return FALSE;
  388.  
  389.     LoadString (GetModuleHandle (NULL), IDS_BKPORTSTATUS, szEvent, MAX_PATH);
  390.     strcat (szEvent, lpBkPort->szFile);
  391.     if (!(lphEvents[BKPORT_STATUS] = CreateEvent (NULL, TRUE, FALSE, szEvent)))
  392.     {
  393.     CloseHandle (lphEvents[BKPORT_ABORT]);
  394.     return FALSE;
  395.     }
  396.  
  397.     /* return success */
  398.     return TRUE;
  399. }
  400.  
  401.  
  402.  
  403.  
  404. void WINAPI DestroyEvents (
  405.     HANDLE    *lphEvents)
  406. {
  407.     /* close event handles */
  408.     CloseHandle (lphEvents[BKPORT_ABORT]);
  409.     CloseHandle (lphEvents[BKPORT_STATUS]);
  410. }
  411.  
  412.  
  413.  
  414.  
  415. int WINAPI NextLineLength (
  416.     char    *lpFilePtr,
  417.     char    *lpFile,
  418.     int     nFileSize)
  419. {
  420.     int    nCnt=0;
  421.     char   *lpf = lpFilePtr;
  422.  
  423.     /* count all characters up to end of file or CR/LF sequence */
  424.     while (lpf                 &&
  425.        lpf-lpFile < nFileSize     &&
  426.        *lpf       != CARRIAGE_RETURN &&
  427.        *(lpf+1)   != LINE_FEED)
  428.     {
  429.     lpf++;
  430.     nCnt++;
  431.     }
  432.  
  433.     /* length plus 3 for CR/LF/0 terminator sequence */
  434.     return nCnt + 3;
  435. }
  436.  
  437.  
  438.  
  439.  
  440. int WINAPI GetNextLine (
  441.     char    *lpFile,
  442.     int     nFileSize,
  443.     char    *lpFilePtr,
  444.     char    *lpLine,
  445.     BOOL    *bCommentOn)
  446. {
  447.     char    *lpf = lpFilePtr;
  448.     char    *lpl = lpLine;
  449.  
  450.     /* copy all characters up to end of file or CR/LF sequence */
  451.     while (lpf                 &&
  452.        lpf-lpFile < nFileSize     &&
  453.        *lpf       != CARRIAGE_RETURN &&
  454.        *(lpf+1)   != LINE_FEED)
  455.     *lpl++ = *lpf++;
  456.  
  457.     /* check for end of buffer */
  458.     if (lpf-lpFile >= nFileSize)
  459.     return EOF_LINE;
  460.  
  461.     /* copy carriage return and line feed to line and terminate */
  462.     *lpl++ = *lpf++;
  463.     *lpl++ = *lpf++;
  464.     *lpl = 0;
  465.  
  466.     /* increment lpl to first non space character in line */
  467.     lpl = lpLine;
  468.     while (*lpl == ' ')
  469.     lpl++;
  470.  
  471.     /* see if single line comments exist */
  472.     if (*lpl     == '/' &&
  473.     *(lpl+1) == '/')
  474.     return COMMENT_LINE;
  475.  
  476.     /* see if comments begin */
  477.     if (*lpl     == '/'  &&
  478.     *(lpl+1) == '*')
  479.     *bCommentOn = TRUE;
  480.  
  481.     /* if comment on, see if it terminates yet */
  482.     if (*bCommentOn)
  483.     {
  484.     lpl = lpLine;
  485.     while (*lpl)
  486.         {
  487.         if (*lpl     == '*'  &&
  488.         *(lpl+1) == '/')
  489.         {
  490.         *bCommentOn = FALSE;
  491.         break;
  492.         }
  493.         lpl = CharNext(lpl);
  494.         }
  495.  
  496.     /* if more text on line, valid line */
  497.     while (*lpl)
  498.         if (*lpl != '*'     &&
  499.         *(lpl+1) != '/')
  500.         return VALID_LINE;
  501.         else
  502.         return COMMENT_LINE;
  503.     }
  504.  
  505.     /* if haven't returned yet, must be valid line */
  506.     return VALID_LINE;
  507. }
  508.