FWATCH.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:11k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /**********************************************************************
  2.    File name: fwatch.c
  3.       Main source file for sample demonstrating use of file change
  4.       notification APIs.
  5.    Functions:
  6.       CheckChangedFile()      - Gets and displays change information
  7.       HandleDirectoryChange() - Watch function
  8.       WatchDirectories()      - Starts the watch
  9.       main()                  - Program main
  10.    Written by Microsoft Product Support Services, Windows Developer Support.
  11.    Copyright 1996-1997 Microsoft Corporation. All rights reserved.
  12. **********************************************************************/
  13. #define UNICODE
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <conio.h>
  17. #include <windows.h>
  18. #define MAX_DIRS    10
  19. #define MAX_FILES   255
  20. #define MAX_BUFFER  4096
  21. // this is the all purpose structure that contains  
  22. // the interesting directory information and provides
  23. // the input buffer that is filled with file change data
  24. typedef struct _DIRECTORY_INFO {
  25. HANDLE      hDir;
  26. TCHAR       lpszDirName[MAX_PATH];
  27. CHAR        lpBuffer[MAX_BUFFER];
  28. DWORD       dwBufLength;
  29. OVERLAPPED  Overlapped;
  30. }DIRECTORY_INFO, *PDIRECTORY_INFO, *LPDIRECTORY_INFO;
  31. DIRECTORY_INFO  DirInfo[MAX_DIRS];        // Buffer for all of the directories
  32. TCHAR           FileList[MAX_FILES*MAX_PATH];   // Buffer for all of the files
  33. DWORD           numDirs;
  34. /**********************************************************************
  35.    CheckChangedFile()
  36.    Purpose:
  37.       This function prints out information when one of the files we
  38.       are watching is changed.
  39.    Parameters:
  40.       LPDIRECTORY_INFO lpdi - Information about the watched directory
  41.       PFILE_NOTIFY_INFORMATION lpfni - Information about modified file
  42.    Return Value:
  43.       None
  44.    Comments:
  45. ********************************************************************/
  46. void WINAPI CheckChangedFile( LPDIRECTORY_INFO lpdi,
  47.                               PFILE_NOTIFY_INFORMATION lpfni)
  48. {
  49.     TCHAR      szFullPathName[MAX_PATH];
  50.     TCHAR      *p;
  51.     HANDLE     hFile;
  52.     FILETIME   LocalFileTime;
  53.     SYSTEMTIME SystemTime;
  54.     BY_HANDLE_FILE_INFORMATION FileInfo;
  55.     p = FileList;
  56.     while(*p && lstrcmpi(p,lpfni->FileName))
  57.         p+=(lstrlen(p)+1);
  58.     if(*p)
  59.     {
  60.         lstrcpy( szFullPathName, lpdi->lpszDirName );
  61.         lstrcat( szFullPathName, L"\" );
  62.         lstrcat( szFullPathName, lpfni->FileName );
  63.         // we assume that the file was changed, since 
  64.         // that is the only thing we look for in this sample
  65.         wprintf( L"%s changed,", szFullPathName );
  66.         hFile=CreateFile( szFullPathName,
  67.                           GENERIC_READ,
  68.                           FILE_SHARE_READ,
  69.                           NULL,
  70.                           OPEN_EXISTING,
  71.                           FILE_FLAG_SEQUENTIAL_SCAN,
  72.                           0);
  73.         GetFileInformationByHandle( hFile, &FileInfo );
  74.         FileTimeToLocalFileTime( &(FileInfo.ftLastWriteTime), &LocalFileTime );
  75.         FileTimeToSystemTime( &LocalFileTime, &SystemTime );
  76.         wprintf( L" Size = %d bytes,", FileInfo.nFileSizeLow );
  77.         wprintf( L" Last Access = %02d/%02d/%02d %02d:%02d:%02d",
  78.                  SystemTime.wMonth,
  79.                  SystemTime.wDay,
  80.                  SystemTime.wYear,
  81.                  SystemTime.wHour,
  82.                  SystemTime.wMinute,
  83.                  SystemTime.wSecond );
  84.         CloseHandle( hFile );
  85.         wprintf( L"n" );
  86.     }
  87. }
  88. /**********************************************************************
  89.    HandleDirectoryChanges()
  90.    Purpose:
  91.       This function receives notification of directory changes and
  92.       calls CheckChangedFile() to display the actual changes. After
  93.       notification and processing, this function calls
  94.       ReadDirectoryChangesW to reestablish the watch.
  95.    Parameters:
  96.       HANDLE hCompPort - Handle for completion port
  97.    Return Value:
  98.       None
  99.    Comments:
  100. ********************************************************************/
  101. void WINAPI HandleDirectoryChange( DWORD dwCompletionPort )
  102. {
  103.     DWORD numBytes;
  104.     DWORD cbOffset;
  105.     LPDIRECTORY_INFO di;
  106.     LPOVERLAPPED lpOverlapped;
  107.     PFILE_NOTIFY_INFORMATION fni;
  108.     do
  109.     {
  110.         // Retrieve the directory info for this directory
  111.         // through the completion key
  112.         GetQueuedCompletionStatus( (HANDLE) dwCompletionPort,
  113.                                    &numBytes,
  114.                                    (LPDWORD) &di,
  115.                                    &lpOverlapped,
  116.                                    INFINITE);
  117.         if ( di )
  118.         {
  119.             fni = (PFILE_NOTIFY_INFORMATION)di->lpBuffer;
  120.             do
  121.             {
  122.                 cbOffset = fni->NextEntryOffset;
  123.                 if( fni->Action == FILE_ACTION_MODIFIED )
  124.                     CheckChangedFile( di, fni );
  125.                 fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE) fni + cbOffset);
  126.             } while( cbOffset );
  127.             // Reissue the watch command
  128.             ReadDirectoryChangesW( di->hDir,di->lpBuffer,
  129.                                    MAX_BUFFER,
  130.                                    TRUE,
  131.                                    FILE_NOTIFY_CHANGE_LAST_WRITE,
  132.                                    &di->dwBufLength,
  133.                                    &di->Overlapped,
  134.                                    NULL);
  135.         }
  136.     } while( di );
  137. }
  138. /**********************************************************************
  139.    WatchDirectories()
  140.    Purpose:
  141.       This function implements the ReadDirectoryChangesW API for
  142.       indicated directories. For each directory watched, a thread
  143.       is created which waits for changes to the directory. This
  144.       function waits for the user to input 'q', then cleans up and
  145.       quits.
  146.    Parameters:
  147.       HANDLE hCompPort - Handle for completion port
  148.    Return Value:
  149.       None
  150. ********************************************************************/
  151. void WINAPI WatchDirectories( HANDLE hCompPort )
  152. {
  153.     DWORD   i;
  154.     DWORD   tid;
  155.     HANDLE  hThread;
  156.     // Start watching each of the directories of interest
  157.     for (i=0;i<numDirs;i++)
  158.     {
  159.         ReadDirectoryChangesW( DirInfo[i].hDir,
  160.                                DirInfo[i].lpBuffer,
  161.                                MAX_BUFFER,
  162.                                TRUE,
  163.                                FILE_NOTIFY_CHANGE_LAST_WRITE,
  164.                                &DirInfo[i].dwBufLength,&DirInfo[i].Overlapped,
  165.                                NULL);
  166.     }
  167.     // Create a thread to sit on the directory changes
  168.     hThread = CreateThread( NULL,
  169.                             0,
  170.                             (LPTHREAD_START_ROUTINE) HandleDirectoryChange,
  171.                             hCompPort,
  172.                             0,
  173.                             &tid);
  174.     // Just loop and wait for the user to quit
  175.     while (getch() != 'q');
  176.     // The user has quit - clean up
  177.     PostQueuedCompletionStatus( hCompPort, 0, 0, NULL );
  178.     // Wait for the Directory thread to finish before exiting
  179.     WaitForSingleObject( hThread, INFINITE );
  180.     CloseHandle( hThread );
  181. }
  182. /**********************************************************************
  183.    main()
  184.    Purpose:
  185.       Main entry-point for fwatch sample. This function reads an .ini
  186.       file (fwatch.ini) to determine which directories and files to
  187.           watch. For each directory watched some information is gathered
  188.       and stored.
  189.    Return Value:  (see errors.h for description)
  190.       None
  191.    Comments:
  192. ********************************************************************/
  193. void main(int argc, char *argv[])
  194. {
  195.     TCHAR   *p,*q;                          // Temporary String Pointer
  196.     HANDLE  hCompPort=NULL;                 // Handle To a Completion Port
  197.     DWORD   i;                              // You always need an I.
  198.     TCHAR   DirList[MAX_DIRS*MAX_PATH];     // Buffer for all of the directories
  199.     TCHAR   IniFile[MAX_PATH];
  200.     TCHAR   FilePath[MAX_PATH];
  201.     HANDLE  hFile;
  202.     GetCurrentDirectory( MAX_PATH, IniFile );
  203.     lstrcat( IniFile, L"\fwatch.ini" );
  204.     GetPrivateProfileString( L"Directories",
  205.                              NULL,
  206.                              NULL,
  207.                              DirList,
  208.                              MAX_DIRS*MAX_PATH,
  209.                              IniFile );
  210.     GetPrivateProfileString( L"Files",
  211.                              NULL,
  212.                              NULL,
  213.                              FileList,
  214.                              MAX_FILES*MAX_PATH,
  215.                              IniFile );
  216.     wprintf( L"Watching these directories:n" );
  217.     // First, walk through the raw list and count items, creating
  218.     // an array of handles for each directory
  219.     for (p=DirList;*p!='';numDirs++,p+=(lstrlen(p)+1))
  220.     {
  221.         if( CreateDirectory( p, NULL ) )
  222.             wprintf( L"Directory %s createdn", p );
  223.         else
  224.             wprintf( L"Directory %s existsn", p );
  225.         // Get a handle to the directory
  226.         DirInfo[numDirs].hDir = CreateFile( p,
  227.                                             FILE_LIST_DIRECTORY,
  228.                                             FILE_SHARE_READ |
  229.                                             FILE_SHARE_WRITE |
  230.                                             FILE_SHARE_DELETE,
  231.                                             NULL,
  232.                                             OPEN_EXISTING,
  233.                                             FILE_FLAG_BACKUP_SEMANTICS |
  234.                                             FILE_FLAG_OVERLAPPED,
  235.                                             NULL);
  236.         if( DirInfo[numDirs].hDir == INVALID_HANDLE_VALUE )
  237.         {
  238.             wprintf( L"Unable to open directory %s. GLE=%d. Terminating...n",
  239.                      p, GetLastError() );
  240.             exit( 0 );
  241.         }
  242.         for (q=FileList;*q!='';q+=(lstrlen(q)+1))
  243.         {
  244.             lstrcpy( FilePath, p );
  245.             lstrcat( FilePath, L"\" );
  246.             lstrcat( FilePath, q );
  247.             if( hFile = CreateFile( FilePath,
  248.                                     GENERIC_WRITE,
  249.                                     FILE_SHARE_READ |
  250.                                     FILE_SHARE_WRITE |
  251.                                     FILE_SHARE_DELETE,
  252.                                     NULL,
  253.                                     CREATE_ALWAYS,
  254.                                     FILE_ATTRIBUTE_NORMAL,
  255.                                     NULL) )
  256.             {
  257.                 wprintf( L"  File %s createdn", FilePath );
  258.                 CloseHandle( hFile );
  259.             }
  260.             else
  261.                 wprintf( L"  File %s could not be createdn", FilePath );
  262.         }
  263.         lstrcpy( DirInfo[numDirs].lpszDirName, p );
  264.         // Set up a key(directory info) for each directory
  265.         hCompPort=CreateIoCompletionPort( DirInfo[numDirs].hDir,
  266.                                           hCompPort,
  267.                                           (DWORD) &DirInfo[numDirs],
  268.                                           0);
  269.     }
  270.     wprintf( L"nnPress <q> to exitn" );
  271.     // Start watching
  272.     WatchDirectories( hCompPort );
  273.     for(i=0;i<numDirs;i++)
  274.         CloseHandle( DirInfo[i].hDir );
  275.     CloseHandle( hCompPort );
  276. }