Example #1
0
// entry point
int main()
{
  int err;
  char key = '\0';

  SetConsoleTitle( "Direct Connect P2P" );

  SetupWinsock();
  DisplaySplash();

  do {
    if ( _kbhit() )
    {
      key = (char) _getch();

      switch ( key )
      {
        case '1':
          WaitForFile();
          break;
        case '2':
          SendFileTo();
          break;
      }
    }
    Sleep( 1 );
  } while ( key != 'q' );
  
  err = closesocket( sTCP );
  ErrCheck( err, 69 );

  err = WSACleanup();
  ErrCheck( err, 80 );

  return 0;
}
void WatchDirectory(void *thread_data) {
  // Copy thread inputs to local variables
  MediaScan *s = ((thread_data_type *)thread_data)->s;
  LPTSTR lpDir = ((thread_data_type *)thread_data)->lpDir;

  // Data variables for the windows directory change notification
  OVERLAPPED oOverlap;
  FILE_NOTIFY_INFORMATION Buffer[FILE_BUFFER_SZ];
  char buf[256];
  char full_path[MAX_PATH_STR_LEN];
  DWORD BytesReturned;

  // Overlapped I/O variables
  WSAOVERLAPPED RecvOverlapped;
  HANDLE hDir;
  DWORD dwWaitStatus;
  DWORD dwBytesRead;
  BOOL bResult;
  WSABUF DataBuf;
  DWORD RecvBytes, Flags;
  char buffer[DATA_BUFSIZE];
  int rc = 0;
  int err = 0;
  char *pBase = 0;

  // Thread state variables
  int ThreadRunning = TRUE;

  // Initialize the cache database
  if (!init_bdb(s)) {
    MediaScanError *e = error_create("", MS_ERROR_CACHE, "Unable to initialize libmediascan cache");
    send_error(s, e);
  }

  SecureZeroMemory(buffer, DATA_BUFSIZE);

  // Make sure the RecvOverlapped struct is zeroed out
  SecureZeroMemory((PVOID) & oOverlap, sizeof(OVERLAPPED));

  // Create the event that will get fired when a directory changes
  oOverlap.hEvent = CreateEvent(NULL, // default security attributes
                                TRUE, // manual-reset event
                                FALSE,  // initial state is nonsignaled
                                TEXT("MyFileChangeEvent")); // "FileChangeEvent" name

  // Make sure the RecvOverlapped struct is zeroed out
  SecureZeroMemory((PVOID) & RecvOverlapped, sizeof(WSAOVERLAPPED));

  // Create an event handle and setup an overlapped structure.
  RecvOverlapped.hEvent = WSACreateEvent();
  if (RecvOverlapped.hEvent == NULL) {
    LOG_ERROR("WSACreateEvent failed: %d\n", WSAGetLastError());
    return;
  }

  DataBuf.len = DATA_BUFSIZE;
  DataBuf.buf = buffer;

  // Open the directory that we are going to have windows monitor, note the share modes
  hDir = CreateFile(lpDir,      // pointer to the file name
                    FILE_LIST_DIRECTORY,  // access (read/write) mode
                    FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, // share mode
                    NULL,       // security descriptor
                    OPEN_EXISTING,  // how to create
                    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,  // file attributes
                    NULL);      // file with attributes to copy

  // Tell windows to monitor the folder asyncroniously using overlapped I/O
  ReadDirectoryChangesW(hDir,   // handle to directory
                        &Buffer,  // read results buffer
                        FILE_BUFFER_SZ * sizeof(FILE_NOTIFY_INFORMATION), // length of buffer
                        TRUE,   // Monitor sub-directories = TRUE
                        DETECTION_FILTER, // filter conditions
                        &BytesReturned, // bytes returned
                        &oOverlap,  // We are using overlapped I/O
                        NULL);  // Not using completion routine

  Flags = 0;
/* XXX FIXME, reqpipe is gone
  rc = WSARecv(s->thread->reqpipe[0], &DataBuf, 1, &RecvBytes, &Flags, &RecvOverlapped, NULL);
  if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
    LOG_ERROR("WSARecv failed with error: %d\n", err);
    return;
  }
*/

  // Run until we are told to stop. It is important to let the thread clean up after itself so
  // there is shutdown code at the bottom of this function.
  while (ThreadRunning) {

    // Set up the events are going to wait for
    HANDLE event_list[2] = { oOverlap.hEvent, RecvOverlapped.hEvent };
    FILE_NOTIFY_INFORMATION *fni;
    LOG_LEVEL(1, "\nWaiting for notification...\n");

    // Wait forever for notification.
    dwWaitStatus = WaitForMultipleObjects(2,  // number of objects in array
                                          event_list, // array of objects
                                          FALSE,  // wait for any object
                                          INFINITE);  // infinite wait

    switch (dwWaitStatus) {
        // This is for the event oOverlap.hEvent
      case WAIT_OBJECT_0:
        bResult = GetOverlappedResult(hDir, &oOverlap, &dwBytesRead, TRUE);

        pBase = (char *)Buffer;
        do {

          fni = (FILE_NOTIFY_INFORMATION *) pBase;

          // Note pRecord->FileName is in UTF-16, have to convert it to 8 bits
          WideCharToMultiByte(CP_UTF8, 0, fni->FileName,  // the string you have
                              fni->FileNameLength / 2,  // length of the string
                              buf,  // output
                              _countof(buf),  // size of the buffer in bytes - if you leave it zero the return value is the length required for the output buffer
                              NULL, NULL);
          buf[fni->FileNameLength / 2] = 0;


          // Set up a full path to the file to be scanned and call ms_scan_fileCall scan here with the file changed
          strcpy(full_path, lpDir);
          strcat(full_path, "\\");
          strcat(full_path, buf);
          LOG_INFO("Found File Changed: %s", full_path);

          switch (fni->Action) {

            case FILE_ACTION_ADDED:
              LOG_INFO("  file was added\n");

              // We get notifications even while a file is being copied. This will wait 60 seconds for the file to finish.
              if (WaitForFile(full_path, 10)) {
                ms_scan_file(s, full_path, TYPE_UNKNOWN);
              }
              else {
                LOG_ERROR("A file found by the background scanner never finished copying");
              }

              break;
            case FILE_ACTION_REMOVED:
              LOG_INFO("  file was removed\n");
              HandleRemovedFile(s, full_path);
              break;

            case FILE_ACTION_MODIFIED:
              LOG_INFO("	file was modified\n");  // This can be a change in the time stamp or attributes.";
              // We get notifications even while a file is being copied. This will wait 60 seconds for the file to finish.
              if (WaitForFile(full_path, 10)) {
                ms_scan_file(s, full_path, TYPE_UNKNOWN);
              }
              else {
                LOG_ERROR("A file found by the background scanner never finished copying");
              }

              break;
/*            case FILE_ACTION_RENAMED_OLD_NAME:
								LOG_INFO("	file was renamed and this is the old name\n");
              break;
            case FILE_ACTION_RENAMED_NEW_NAME:
								LOG_INFO("	file was renamed and this is the new name\n");
              break;
*/ }

          if (!fni->NextEntryOffset)
            break;
          pBase += fni->NextEntryOffset;
        } while (TRUE);

        SecureZeroMemory((PVOID) Buffer, sizeof(Buffer));
        ReadDirectoryChangesW(hDir, // handle to directory
                              &Buffer,  // read results buffer
                              sizeof(Buffer), // length of buffer
                              TRUE, // Monitor sub-directories = TRUE
                              DETECTION_FILTER, // filter conditions
                              &BytesReturned, // bytes returned
                              &oOverlap,  // We are using overlapped I/O
                              NULL);  // Not using completion routine

        break;                  /* WAIT_OBJECT_0: */

        // This is for the event s->ghSignalEvent
      case WAIT_OBJECT_0 + 1:

        ThreadRunning = FALSE;

        break;                  /* WAIT_OBJECT_0 + 1: */

      case WAIT_TIMEOUT:

        // A timeout occurred, this would happen if some value other
        // than INFINITE is used in the Wait call and no changes occur.
        // In a single-threaded environment you might not want an
        // INFINITE wait.

        LOG_INFO("\nNo changes in the timeout period.\n");
        break;

      default:
        LOG_ERROR("\n ERROR: Unhandled dwWaitStatus.\n");
        ExitThread(GetLastError());
        break;
    }
  }

  // Free the data that was passed to this thread on the heap
  if (thread_data != NULL) {
    free(thread_data);
    thread_data = NULL;         // Ensure address is not reused.
  }

  CancelIo(hDir);

  if (!HasOverlappedIoCompleted(&oOverlap)) {
    SleepEx(5, TRUE);
  }

  WSACloseEvent(RecvOverlapped.hEvent);
  CloseHandle(oOverlap.hEvent);


  ExitThread(GetLastError());

}                               /* WatchDirectory() */