//The implementation of WaitForMultipleObjects. DWORD WaitForMultipleObjects(__COMMON_OBJECT** pObjectArray, int nObjectNum, BOOL bWaitAll, DWORD dwMillionSeconds, int* pnSignalObjectIndex) { DWORD dwRetVal = OBJECT_WAIT_FAILED; int i; //Parameters' validation checking. if((NULL == pObjectArray) || (nObjectNum > MAX_MULTIPLE_WAIT_NUM)) { goto __TERMINAL; } for(i = 0; i < nObjectNum; i ++) { if(!IsSynObject(pObjectArray[i])) { goto __TERMINAL; } } if(bWaitAll) { dwRetVal = WaitForAll(pObjectArray,nObjectNum,dwMillionSeconds,pnSignalObjectIndex); } else { dwRetVal = WaitForAny(pObjectArray,nObjectNum,dwMillionSeconds,pnSignalObjectIndex); } __TERMINAL: return dwRetVal; }
VOID UserScanSynchronizedCancel ( _In_ PUSER_SCAN_CONTEXT Context ) /*++ Routine Description: This routine tries to abort all the scanning threads and wait for them to terminate. Arguments: Context - User scan context, please see userscan.h Return Value: Please consult WaitForMultipleObjects(...) --*/ { ULONG i; PSCANNER_THREAD_CONTEXT scanThreadCtxes = Context->ScanThreadCtxes; if (NULL == scanThreadCtxes) { fprintf(stderr, "Scan thread contexes are NOT suppoed to be NULL.\n"); return; } // // Tell all scanning threads that the program is going to exit. // Context->Finalized = TRUE; // // Signal cancellation events for all scanning threads. // for (i = 0; i < USER_SCAN_THREAD_COUNT; i ++ ) { scanThreadCtxes[i].Aborted = TRUE; } // // Wake up the listening thread if it is waiting for message // via GetQueuedCompletionStatus() // CancelIoEx(Context->ConnectionPort, NULL); // // Wait for all scan threads to complete cancellation, // so we will be able to close the connection port and etc. // WaitForAll(scanThreadCtxes); return; }