//============================================================================= CSaveData::CSaveData() : m_pDataBuffer(NULL), m_FileHandle(NULL), m_ulFrameCount(DEFAULT_FRAME_COUNT), m_ulBufferSize(DEFAULT_BUFFER_SIZE), m_ulFrameSize(DEFAULT_FRAME_SIZE), m_ulBufferPtr(0), m_ulFramePtr(0), m_fFrameUsed(NULL), m_pFilePtr(NULL), m_fWriteDisabled(FALSE), m_bInitialized(FALSE) { PAGED_CODE(); m_waveFormat = NULL; m_FileHeader.dwRiff = RIFF_TAG; m_FileHeader.dwFileSize = 0; m_FileHeader.dwWave = WAVE_TAG; m_FileHeader.dwFormat = FMT__TAG; m_FileHeader.dwFormatLength = sizeof(WAVEFORMATEX); m_DataHeader.dwData = DATA_TAG; m_DataHeader.dwDataLength = 0; RtlZeroMemory(&m_objectAttributes, sizeof(m_objectAttributes)); m_ulStreamId++; InitializeWorkItems(GetDeviceObject()); } // CSaveData
VOID HandleMediaChangeEvent( UINT uidCdRom ) { /* * Local variables */ HANDLE hDevice; ULONG id; DWORD cb; DWORD dwLogicalDrives; DWORD dwDriveMask; DWORD dwDriveCount; DWORD dwRecipients; BOOL bResult; INT nCurrentTry; NTSTATUS Status; UNICODE_STRING ustrCdRom; UNICODE_STRING ustrCdRomId; UNICODE_STRING ustrAnyCdRom; UNICODE_STRING ustrNtPath; DEV_BROADCAST_VOLUME dbcvInfo; LPWSTR lpszCdRom = TEXT("\\Device\\CdRom"); WCHAR szDrive[] = TEXT("A:\\"); WCHAR szDevice[] = TEXT("\\\\.\\A:"); WCHAR wcDrive; WCHAR szCdRom[32]; WCHAR szBuff[256]; UserAssert(uidCdRom >= 0 && uidCdRom < NUM_MEDIA_EVENTS); // at most 24 cd-rom drives in system /* * Some initializations */ RtlInitUnicodeString( &ustrAnyCdRom, lpszCdRom ); wcDrive = UNICODE_NULL; /* * Form the \Device\CdRomX name based on uidCdRom */ wsprintfW( szCdRom, L"\\Device\\CdRom%d", uidCdRom ); RtlInitUnicodeString( &ustrCdRom, szCdRom ); /* * The uidCdRom parameter tells us which CD-ROM device generated the * MediaChange event. We need to map this device back to it's logical * drive letter because WM_DEVICECHANGE is based on drive letters. * * To avoid always searching all logical drives, we cache the last * associated drive letter. We still need to check this every time * we get notified because WinDisk can remap drive letters. */ if (wcDriveCache[uidCdRom]) { /* * Convert our DOS path name to a NT path name */ ustrNtPath.MaximumLength = sizeof(szBuff); ustrNtPath.Length = 0; ustrNtPath.Buffer = szBuff; bResult = GetDeviceObject(wcDriveCache[uidCdRom], &ustrNtPath); if (bResult) { /* * Check to see if this drive letter is the one that maps * to the CD-ROM drive that just notified us. */ if (RtlEqualUnicodeString(&ustrCdRom, &ustrNtPath, TRUE)) { /* * Yes, we found a match */ wcDrive = wcDriveCache[uidCdRom]; } } } if (!wcDrive) { /* * Either the cache wasn't initialized, or we had a re-mapping * of drive letters. Scan all drive letters looking for CD-ROM * devices and update the cache as we go. */ RtlZeroMemory(wcDriveCache, sizeof(wcDriveCache)); szDrive[0] = L'A'; szDevice[4] = L'A'; dwDriveCount = 26; //Max number of drive letters dwDriveMask = 1; //Max number of drive letters dwLogicalDrives = GetLogicalDrives(); while (dwDriveCount) { /* * Is this logical drive a CD-ROM? */ // // JOHNC - Remove after GetDriveType() is fixed if ((dwLogicalDrives & dwDriveMask) && GetDriveType(szDrive) == DRIVE_CDROM) { /* * For this CD-ROM drive, find it's NT path. */ ustrNtPath.MaximumLength = sizeof(szBuff); ustrNtPath.Length = 0; ustrNtPath.Buffer = szBuff; bResult = GetDeviceObject(szDrive[0], &ustrNtPath); if (bResult) { /* * Make sure the string is in the form \Device\CdRom */ if (RtlPrefixUnicodeString(&ustrAnyCdRom, &ustrNtPath, TRUE)) { /* * Now find it's id. We have a string that looks like * \Device\CdRom??? where ??? is the unit id */ RtlInitUnicodeString(&ustrCdRomId, (PWSTR)((PSTR)(ustrNtPath.Buffer)+ustrAnyCdRom.Length)); RtlUnicodeStringToInteger(&ustrCdRomId, 10, &id); UserAssert(id >= 0 && id < NUM_MEDIA_EVENTS); wcDriveCache[id] = szDrive[0]; //Initially set State to Unknown aDriveState[id] = DS_UNKNOWN; /* * If this is the device that notified us, remember its * drive letter so we can broadcase WM_DEVICECHANGE */ if (uidCdRom == id) { wcDrive = szDrive[0]; } } } } /* * Try the next drive */ szDrive[0] = szDrive[0] + 1; szDevice[4] = szDevice[4] + 1; dwDriveMask <<= 1; --dwDriveCount; } } /* * If we found a logical drive, determine the media state for the drive * and broadcast the WM_DEVICECHANGE notification. */ if (wcDrive) { /* * Get the Media status of this drive. Assume media is not * present in the case of an error. */ szDevice[4] = wcDrive; hDevice = CreateFile(szDevice, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == INVALID_HANDLE_VALUE) { #ifdef DEBUG KdPrint((" CreateFile( '%ls' ) Failed. Error %lx\n", szDevice,GetLastError())); #endif return; } /* * Loop and check the CD-ROM to see if media is available. We need * this loop because some CD-ROM drives notify us that media has * arrived before the drive has recognized that it had new media. */ for (nCurrentTry = 0; nCurrentTry < MAX_TRIES; nCurrentTry++) { /* * See if media is present */ bResult = (DWORD)DeviceIoControl(hDevice, IOCTL_DISK_CHECK_VERIFY, NULL, 0, NULL, 0, &cb, NULL); if (bResult) { /* * Media is present, change the state to Inserted. */ aDriveState[uidCdRom] = DS_INSERTED; break; } /* * Media wasn't present, so we need to look at GetLastError() to see * if DeviceIoControl() failed. If so we may want to try again. */ if (GetLastError() == ERROR_NOT_READY) { Sleep(500); // 1/2 second /* * We only want to retry if we the prev State was UNKNOWN or * EJECTED. If the previous State was INSERTED it means that * this event is the removal event */ if(aDriveState[uidCdRom]== DS_UNKNOWN || aDriveState[uidCdRom] == DS_EJECTED) { continue; } } /* * Call failed. Assume worst case and say the media has been removed. */ aDriveState[uidCdRom] = DS_EJECTED; break; } /* * Close the handle to the CD-ROM device */ CloseHandle(hDevice); /* * Initialize the structures used for BroadcastSystemMessage */ dbcvInfo.dbcv_size = sizeof(dbcvInfo); dbcvInfo.dbcv_devicetype = DBT_DEVTYP_VOLUME; dbcvInfo.dbcv_reserved = 0; dbcvInfo.dbcv_flags = DBTF_MEDIA; dbcvInfo.dbcv_unitmask = (1 << (wcDrive - L'A')); dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS; /* * Temporarily we must assign this thread to a desktop so we can * call USER's BroascastSystemMessage() routine. We call the * private SetThreadDesktopToDefault() to assign ourselves to the * desktop that is currently receiving input. */ Status = NtUserSetInformationThread(NtCurrentThread(), UserThreadUseActiveDesktop, NULL, 0); if (NT_SUCCESS(Status)) { /* * Broadcast the message */ BroadcastSystemMessage(BSF_FORCEIFHUNG, &dwRecipients, WM_DEVICECHANGE, // HACK: need to or 0x8000 in wParam // because this is a flag to let // BSM know that lParam is a pointer // to a data structure. 0x8000 | ((bResult) ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE), (LPARAM)&dbcvInfo); #ifdef DEBUG KdPrint((" Message Broadcast for '%lc:'\n", wcDrive)); #endif /* * Set our thread's desktop back to NULL. This will decrement * the desktop's reference count. */ hDevice = NULL; NtUserSetInformationThread(NtCurrentThread(), UserThreadUseDesktop, &hDevice, // hDevice = NULL sizeof(HANDLE)); } } }