⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdc.c

📁 <Win2k系统编程>源码.次数为国人自编,内容丰富,还是不错的.
💻 C
📖 第 1 页 / 共 5 页
字号:
                   );
            CloseHandle( File );
            return;
            }
        }

    //
    // We have successfully opened the file and are ready to go.
    // Allocate space for a search request and fill it in
    // with the information needed by the ProcessSearchFile
    // function when it runs.
    //

    SearchRequest = LocalAlloc( LMEM_ZEROINIT,
                                sizeof( *SearchRequest ) +
                                    strlen( Path ) + 1
                              );
    if (SearchRequest == NULL) {
        fprintf( stderr, "PDC: Out of memory\n" );
        exit( 1 );
        }

    SearchRequest->WorkItem.Reason = WORK_ITEM;
    SearchRequest->File = File;
    SearchRequest->FileSize = FileSize;
    SearchRequest->FileData = FileData;
    strcpy( SearchRequest->FullPathName, Path );

    if (!ASyncIO) {
        //
        // If not using asynchronous I/O, then queue the search
        // request to the work queue.
        //

        QueueWorkItem( WorkQueue, &SearchRequest->WorkItem );
        }
    else {
        //
        // Using asynchronous I/O, so queue the read operation.
        // The file handle must remain open while the read operation
        // is pending.
        //

        if (!ReadFileEx( File,
                         FileData,
                         FileSize,
                         &SearchRequest->OverlappedIO,
                         (LPOVERLAPPED_COMPLETION_ROUTINE) ProcessReadFileCompletion
                       )
           ) {
            fprintf( stderr, "%s(0) : error %u: Unable to queue read of file.\n",
                     Path,
                     GetLastError()
                   );

            VirtualFree( FileData, 0, MEM_RELEASE );
            CloseHandle( File );
            LocalFree( SearchRequest );
            return;
            }


        //
        // Successfully queued the read operation.  Keep a count
        // of outstanding read operations so we know when it is
        // okay to terminate.
        //

        OutstandingIOOperations += 1;
        }

    //
    // Return back to the EnumerateDirectoryTree function so that it
    // can call us with the next file or directrry.
    //

    return;
}



VOID
ProcessRequest(
    IN PWORK_QUEUE_ITEM WorkItem
    )

/*++

Routine Description:

    This function is called whenever a work item is removed from
    the work queue by one of the worker threads.  Which worker
    thread context this function is called in is arbitrary.

    This functions keeps a pointer to state information in
    thread local storage.

    This function is called once at the beginning with a
    special initialization call.  During this call, this
    function allocates space for state information and
    remembers the pointer to the state information in
    a Thread Local Storage (TLS) slot.

    This function is called once at the end with a special
    termination call.  During this call, this function
    frees the state information allocated during the
    initialization call.

    In between these two calls are zero or more calls to
    handle a work item.  The work item is a search request
    which is handled by the ProcessSearchFile function.

Arguments:

    WorkItem - Supplies a pointer to the work item just removed
        from the work queue.  It is the responsibility of this
        routine to free the memory used to hold the work item.

Return Value:

    None.

--*/

{
    DWORD BytesWritten;
    PSEARCH_REQUEST_STATE State;
    PSEARCH_REQUEST SearchRequest;
    CHAR MessageBuffer[ 2 * MAX_PATH ];

    if (WorkItem->Reason == WORK_INITIALIZE_ITEM) {
        //
        // First time initialization call.  Allocate space for
        // state information.
        //

        State = LocalAlloc( LMEM_ZEROINIT,
                            sizeof( *State )
                          );

        if (State != NULL) {
            //
            // Now create a virtual buffer, with an initial commitment
            // of zero and a maximum commitment of 128KB.  This buffer
            // will be used to accumulate the matched strings output
            // during the search of a single file.  This is so the
            // output can be written to standard output with a single
            // write call, thus insuring that it remains contiguous
            // in the output stream, and is not intermingled with the
            // output of the other worker threads.
            //

            if (CreateVirtualBuffer( &State->Buffer, 0, 2 * 64 * 1024 )) {
                //
                // The CurrentOutput field of the state block is
                // a pointer to where the next output goes in the
                // buffer.  It is initialized here and reset each
                // time the buffer is flushed to standard output.
                //

                State->CurrentOutput = State->Buffer.Base;
                }
            else {
                LocalFree( State );
                State = NULL;
                }
            }

        //
        // Remember the pointer to the state informaiton
        // thread local storage.
        //

        TlsSetValue( TlsIndex, State );
        return;
        }

    //
    // Here to handle a work item or special terminate call.
    // Get the state pointer from thread local storage.
    //

    State = (PSEARCH_REQUEST_STATE)TlsGetValue( TlsIndex );
    if (State == NULL) {
        return;
        }

    //
    // If this is the special terminate work item, free the virtual
    // buffer and state block allocated above and set the thread
    // local storage value to NULL.  Return to caller.
    //

    if (WorkItem->Reason == WORK_TERMINATE_ITEM) {
        FreeVirtualBuffer( &State->Buffer );
        LocalFree( State );
        TlsSetValue( TlsIndex, NULL );
        return;
        }

    //
    // If not an initialize or terminate work item, then must be a
    // search request.  Calculate the address of the search request
    // block, based on the position of the WorkItem field in the
    // SEARCH_REQUEST structure.
    //

    SearchRequest = CONTAINING_RECORD( WorkItem, SEARCH_REQUEST, WorkItem );

    //
    // Actual search operation is protected by a try ... except
    // block so that any attempts to store into the virtual buffer
    // will be handled correctly by extending the virtual buffer.
    //

    _try {
        //
        // Perform the search against this file.
        //

        ProcessSearchFile( SearchRequest, State );

        //
        // Done with this file.  If using asynchronous I/O, decrement the
        // count of outstanding I/O operations and it if goes to zero,
        // then signal the IoCompletedEvent as there are no more outstanding
        // I/O operations.
        //

        if (ASyncIO && InterlockedDecrement( &OutstandingIOOperations ) == 0) {
            SetEvent( IoCompletedEvent );
            }

        //
        // If any output was written to the virtual buffer,
        // flush the output to standard output.  Trim the
        // virtual buffer back to zero committed pages.
        //

        if (State->CurrentOutput > (LPSTR)State->Buffer.Base) {
            WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ),
                       State->Buffer.Base,
                       State->CurrentOutput - (LPSTR)State->Buffer.Base,
                       &BytesWritten,
                       NULL
                     );

            TrimVirtualBuffer( &State->Buffer );
            State->CurrentOutput = (LPSTR)State->Buffer.Base;
            }
        }

    _except( VirtualBufferExceptionFilter( GetExceptionCode(),
                                          GetExceptionInformation(),
                                          &State->Buffer
                                        )
          ) {

        //
        // We will get here if the exception filter was unable to
        // commit the memory.
        //

        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ),
                   MessageBuffer,
                   sprintf( MessageBuffer,
                            "%s(0) : error 0: too many matches for file\n",
                            SearchRequest->FullPathName
                          ),
                   &BytesWritten,
                   NULL
                 );
        }

    //
    // Free the storage used by the SearchRequest
    //

    LocalFree( SearchRequest );

    //
    // All done with this request.  Return to the worker thread that
    // called us.
    //

    return;
}



VOID
ProcessReadFileCompletion(
    DWORD dwErrorCode,
    DWORD dwNumberOfBytesTransfered,
    LPOVERLAPPED lpOverlapped
    )

/*++

Routine Description:

    This function is called whenever an asynchronous I/O operation,
    queued by the previous function, completes.  This function
    calulates the address of the search request block and then
    queue the request to the work queue, now that the data is
    in memory.

Arguments:

    dwErrorCode - Supplies the error code that the I/O completed with.

    dwNumberOfBytesTransfered - Supplies the actual number of bytes
        transferred.

    lpOverlapped - Supplies a pointer to the structure given to
        ReadFileEx when the I/O operation was queued.

Return Value:

    None.

--*/

{
    PSEARCH_REQUEST SearchRequest;

    //
    // Since the data we need is now in memory, queue the search
    // request to the work queue.
    //

    SearchRequest = CONTAINING_RECORD( lpOverlapped, SEARCH_REQUEST, OverlappedIO );
    QueueWorkItem( SearchRequest->WorkItem.WorkQueue, &SearchRequest->WorkItem );
}



VOID
ProcessSearchFile(
    IN PSEARCH_REQUEST SearchRequest,
    IN PSEARCH_REQUEST_STATE State
    )

/*++

Routine Description:

    This function performs the actual search of the contents of the
    passed file for the search string given on the command line.
    If we are using synchronous I/O, then do the read operation
    now.

    Search the contents of the file for any matches, and accumulate
    the match output in the virtual buffer using sprintf, which is
    multi-thread safe, even with the single threaded version of
    the libraries.

Arguments:

    SearchRequest - Supplies a pointer to the search request which
        contains the relevant information.

    State - Supplies a pointer to state information for the current
        thread.

Return Value:

    None.

--*/

{
    LPSTR FileData, s, s1, BegLine, EndLine, EndOfFile;
    DWORD LineNumber;
    DWORD MatchesFound;
    DWORD BytesRead;

    // Get a pointer to the beginning of the file data in memory
    // and calculate the address of the end of file point in
    // memory.
    //

    FileData = SearchRequest->FileData;
    EndOfFile = FileData + SearchRequest->FileSize;

    //
    // If using synchronous I/O, then we have not read in the
    // file contents yet, so issue the synchronous read to get
    // the data into memory.
    //

    if (SyncIO) {
        if (!ReadFile( SearchRequest->File,
                       FileData,
                       SearchRequest->FileSize,
                       &BytesRead,
                       NULL
                     ) ||
            BytesRead != SearchRequest->FileSize
           ) {
            State->CurrentOutput += sprintf( State->CurrentOutput,
                                             "%s(0) : error %u: Unable to read file contents.\n",
                                             SearchRequest->FullPathName,
                                             GetLastError()
                                           );

            CloseHandle( SearchRequest->File );
            return;
            }
        }

    //
    // Close any open file handle associated with this request.
    //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -