Ejemplo n.º 1
0
VOID unmount()
{
    DokanUnmountType Unmount = NULL;
    HMODULE dokanDll = LoadLibraryW(DOKAN_DLL);
    if (dokanDll) Unmount=(DokanUnmountType)GetProcAddress(dokanDll, "DokanUnmount");

    if (mountPoint[0] != 'a' && Unmount)
    {
        debug(D_NOTICE, "Unmounting %s ...", mountPoint);
        setVolumeIcon(mountPoint[0], false);
        Unmount((WCHAR)mountPoint[0]);
    }
    if (dokanDll) FreeLibrary(dokanDll);

    if (hMountThread && hMountThread != INVALID_HANDLE_VALUE)
    {
        WaitForSingleObject(hMountThread, 1000);
        debug(D_NOTICE, "Closing thread");
        TerminateThread(hMountThread, 0);
        CloseHandle(hMountThread);
        hMountThread = INVALID_HANDLE_VALUE;
    }

    DWORD recipients = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
    BroadcastSystemMessage(0, &recipients, WM_DEVICECHANGE, DBT_CONFIGCHANGED, 0);

    debug(D_NOTICE, "Unmounted!");
    Sleep(2000);
    exit(0);
}
Ejemplo n.º 2
0
VOID mount(mount_params* pparams)
{
    if (hMountThread != INVALID_HANDLE_VALUE)
    {
        debug(D_WARNING, "Already mounted!");
        return;
    }

    hMountThread = CreateThread(NULL, 0, ThreadProc, pparams, 0, NULL);
    if (!hMountThread || hMountThread == INVALID_HANDLE_VALUE)
    {
        debug(D_ERROR, "Failed to create thread!");
        hMountThread = INVALID_HANDLE_VALUE;
        return;
    }

    debug(D_NOTICE, "Thread created");
    int loop = 3;
    while (loop > 0)
    {
        DWORD recipients = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
        BroadcastSystemMessage(0, &recipients, WM_DEVICECHANGE, DBT_CONFIGCHANGED, 0);
        --loop;
    }
}
Ejemplo n.º 3
0
static void BroadcastEndSession(DWORD dwRecipients, LPARAM lParam)
{
	BroadcastSystemMessage(BSF_FORCEIFHUNG, &dwRecipients, WM_ENDSESSION, TRUE, lParam);
}
Ejemplo n.º 4
0
BOOL AppMainApp::InitInstance()
{
	pMainDialogWindowCrypt = NULL;
	pMainDialogWindow=NULL;
	if (!InitATL()){
		return FALSE;
	}
	{// На первый запуск...
		char sz1[128]={0};
		char sz2[128]="1";
		CString sAddCal;
		GetCommandLineParameter("addcal",sAddCal);
		if(sAddCal!=""){
			strcpy(sz1,sAddCal);
			SetRegSetting("", "FR_addCalendar", sz1);
			return FALSE;
		}
		CString sAddClo;
		GetCommandLineParameter("addclo",sAddClo);
		if(sAddClo!=""){
			strcpy(sz2,sAddClo);
			SetRegSetting("", "FR_addClock", sz2);
			return FALSE;
		}
		GetRegSetting("", "FR_addClock", sz1, sizeof(sz1));
		bAddOnStartClo=atol(sz1);
		GetRegSetting("", "FR_addCalendar", sz2, sizeof(sz2));
		bAddOnStartCal=atol(sz2);
	}
	{//setup_file
		// Регистрируем файл
		char szWkmRegistered[32]={0};
		GetRegSetting("", "wpc_setupRegistered", szWkmRegistered, sizeof(szWkmRegistered));
		if(szWkmRegistered[0]==0){
			strcpy(szWkmRegistered,"yes");
			SetRegSetting("", "wpc_setupRegistered", szWkmRegistered);
			RegisterExtension("wpc_setup","WireChanger setup file","-setup_file=");
		}
		CString sSetupFile;
		GetCommandLineParameter("setup_file",sSetupFile);
		if(sSetupFile!=""){
			if(isFileExist(sSetupFile)){
				CString sContent,sKeyPart;
				ReadFile(sSetupFile,sContent);
				CString sXML=CDataXMLSaver::GetInstringPart("<SETUP>","</SETUP>",sContent);
				if(sXML==""){
					sKeyPart=sContent;
				}
				// Делаем что сказано...
				if(sKeyPart!=""){
					SaveFile(GetUserFolder()+LICENSE_KEY_FILE,sKeyPart);
					AfxMessageBox(_l("Registration info installed successfully\nRestart WireChanger to see changes"));
				}
			}else{
				AfxMessageBox(Format("Reading setup file error: '%s' not found!",sSetupFile));
			}
			return FALSE;
		}
	}
	CString sExe;
	GetCommandLineParameter("add",sExe,0);
	if(sExe!=""){_XLOG_
		CString sNewFile=CString(GetApplicationDir())+WP_TEMPLATE+"\\"+GetPathPart(sExe,0,0,1,1);
		BOOL b=CopyFile(sExe,sNewFile,TRUE);
		if(!b){
			AfxMessageBox(_l("Error")+": "+_l("Widget already exist"));
		}
		return FALSE;
	}
    // Глобальные настройки
    CString sDats;
    ReadFile(CString(GetApplicationDir())+"inits.txt",sDats);
    AppName()=PROGNAME;
    AddDefsWallps()=1;
	AddDefsInteract()=1;
	if(sDats.GetLength()){
		CString sAppName=CDataXMLSaver::GetInstringPart("app:[","]",sDats);
		if(sAppName.GetLength()!=0){
			AppName()=sAppName;
		}
		AddDefsWallps()=atol(CDataXMLSaver::GetInstringPart("defs:[","]",sDats));
		AddDefsInteract()=atol(CDataXMLSaver::GetInstringPart("intr:[","]",sDats));
	}
    //===========
	CString sConsoleMode;
	GetCommandLineParameter("console",sConsoleMode);
	CString sIniFileInfo;
	ReadFile(CString(GetApplicationDir())+"install.ini",sIniFileInfo);
	if(sIniFileInfo!=""){
		sIniFileInfo+="\r\n";
	}
	if(sConsoleMode=="yes"){
		CString sConsoleSave,sConsoleRest;
		GetCommandLineParameter("wpsave",sConsoleSave);
		GetCommandLineParameter("wprestore",sConsoleRest);
		if(sConsoleSave=="yes"){
			if(sIniFileInfo.Find("[Main]")==-1){
				sIniFileInfo+="[Main]\r\n";
			}
			
			CString sAID,sDte;
			GetCommandLineParameter("affid",sAID);
			GetCommandLineParameter("date",sDte);
			if(sIniFileInfo.Find("AffId=")==-1){
				sIniFileInfo+=CString("AffId=")+sAID+"\r\n";
			}
			if(sIniFileInfo.Find("Date=")==-1){
				sIniFileInfo+=CString("Date=")+sDte+"\r\n";
			}
			if(sIniFileInfo.Find("CPD-W")==-1){
				CRegKey key;
				key.Open(HKEY_CURRENT_USER, "Control Panel\\Desktop");
				if(key!=NULL){
					char szTemp[MAX_PATH]="";
					DWORD lSize,dwType=0;
					lSize = MAX_PATH;
					if(RegQueryValueEx(key.m_hKey,"Wallpaper",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
						sIniFileInfo+="CPD-W=<";
						sIniFileInfo+=szTemp;
						sIniFileInfo+=">\r\n";
					}
					lSize = MAX_PATH;
					if(RegQueryValueEx(key.m_hKey,"WallpaperStyle",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
						sIniFileInfo+="CPD-WS=<";
						sIniFileInfo+=szTemp;
						sIniFileInfo+=">\r\n";
					}
					lSize = MAX_PATH;
					if(RegQueryValueEx(key.m_hKey,"TileWallpaper",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
						sIniFileInfo+="CPD-WT=<";
						sIniFileInfo+=szTemp;
						sIniFileInfo+=">\r\n";
					}
					lSize = MAX_PATH;
					if(RegQueryValueEx(key.m_hKey,"SCRNSAVE.EXE",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
						sIniFileInfo+="CPD-SS=<";
						sIniFileInfo+=szTemp;
						sIniFileInfo+=">\r\n";
					}
				}
				{// На дефолтного
					CRegKey key;
					key.Open(HKEY_USERS, ".DEFAULT\\Control Panel\\Desktop");
					if(key!=NULL){
						char szTemp[MAX_PATH]="";
						DWORD lSize,dwType=0;
						lSize = MAX_PATH;
						if(RegQueryValueEx(key.m_hKey,"Wallpaper",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
							sIniFileInfo+="DCPD-W=<";
							sIniFileInfo+=szTemp;
							sIniFileInfo+=">\r\n";
						}
						lSize = MAX_PATH;
						if(RegQueryValueEx(key.m_hKey,"WallpaperStyle",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
							sIniFileInfo+="DCPD-WS=<";
							sIniFileInfo+=szTemp;
							sIniFileInfo+=">\r\n";
						}
						lSize = MAX_PATH;
						if(RegQueryValueEx(key.m_hKey,"TileWallpaper",NULL, &dwType,(LPBYTE)szTemp, &lSize)== ERROR_SUCCESS){
							sIniFileInfo+="DCPD-WT=<";
							sIniFileInfo+=szTemp;
							sIniFileInfo+=">\r\n";
						}
					}
				}
			}
			if(sIniFileInfo.Find("UserData")==-1 || sIniFileInfo.Find("ConfigFile")==-1){
				sIniFileInfo+="ConfigFile=";
				sIniFileInfo+=objSettings.sIniFile;
				sIniFileInfo+="\r\n";
				sIniFileInfo+="UserData=";
				sIniFileInfo+=GetPathPart(objSettings.sIniFile,1,1,0,0);
				sIniFileInfo+="\r\n";
			}
			SaveFile(CString(GetApplicationDir())+"install.ini",sIniFileInfo);
		}else if(sConsoleRest=="yes"){
			if(sIniFileInfo==""){
				return 0;
			}
			RestoreWP(sIniFileInfo,1);
		}
		return FALSE;
	}
	CString sWait;
	GetCommandLineParameter("wait",sWait);
	DWORD dwStartWait=GetTickCount();
	if(sWait=="yes"){
		while(CheckProgrammRunState(NULL, UNIQUE_TO_TRUSTEE, false) && GetTickCount()-dwStartWait<180000){
			Sleep(1000);
		}
	}
	// Для нормально работы клонов
	if(IsThisProgrammAlreadyRunning()){
		// || IsOtherProgrammAlreadyRunning("WireChanger")
		DWORD dwTarget=BSM_APPLICATIONS;
		BroadcastSystemMessage(BSF_FORCEIFHUNG | BSF_IGNORECURRENTTASK | BSF_POSTMESSAGE, &dwTarget, iWM_THIS, WPARAM(99), LPARAM(99));
		return FALSE;
	}
	// Столбим уникальное за компьютером...
	CheckProgrammRunState("WC3",UNIQUE_TO_COMPUTER,1,"");
	CString sRestore;
	GetCommandLineParameter("restore",sRestore);
	if(sRestore!="" && isFileExist(sRestore)){
		CString sIniPath=GetPathPart(objSettings.sIniFile,1,1,0,0);
		{//Первый проход
			CZipArchive zipFile;
			if(zipFile.Open(sRestore)){
				ZIP_FIND_DATA pFind;
				HANDLE hSearch=zipFile.FindFirstFile("*.*",&pFind);
				while(zipFile.FindNextFile(hSearch, &pFind)){
					CString sFileName=pFind.szFileName;
					if(sFileName!=""){
						CZipFile zI;
						if(zipFile.GetFile(pFind.nDirIndex,&zI)){
							DeleteFile(sIniPath+sFileName);
							zI.SafeSaveToDosk(sIniPath+sFileName,0);
						}
					}
				}
				zipFile.FindClose(hSearch);
				zipFile.Close();
			}
		}
	}
	AfxEnableControlContainer();
	AfxInitRichEdit();
#if WINVER<=0x0050
#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif
#endif
	OleInitialize(NULL);
	//
	CRYPT_START
	objSettings.sLikUser="";
	objSettings.sLikKey="";
	HANDLE hLicenseFile=::CreateFile(GetUserFolder()+LICENSE_KEY_FILE, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (!hLicenseFile || hLicenseFile==INVALID_HANDLE_VALUE){
		// Из локального каталога!
		hLicenseFile=::CreateFile(CString(GetApplicationDir())+LICENSE_KEY_FILE, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	}
	if (hLicenseFile && hLicenseFile!=INVALID_HANDLE_VALUE){
		DWORD dwRead=0;
		char szKey[2048]="";
		objSettings.sLikKey="";
		::ReadFile(hLicenseFile, szKey, sizeof(szKey), &dwRead, NULL);
		objSettings.sLikUser=CDataXMLSaver::GetInstringPart("user:[","]",szKey);
		objSettings.sLikKey=CDataXMLSaver::GetInstringPart("key:[","]",szKey);
		::CloseHandle(hLicenseFile);
	}
#ifdef LIC_HARDCODED_U
	objSettings.sLikUser=LIC_HARDCODED_U;
#endif
#ifdef LIC_HARDCODED_K
	objSettings.sLikKey=LIC_HARDCODED_K;
#endif
	//if(sIniFileInfo.Find("WireChangerEF")!=-1){
		/*
		WC5Elefun	CCC2-HJ3S-88A6-C4TP
		*/
		/*
		WC5IPv6	4HVF-9XF6-DGQ2-94U2	
		*/
		/*
		WK999IPv6	EJCM-VNR7-GZ8F
		*/
		/*Mapi2Pop3
		IPv6	GT8N-6747-AGDM
		*/
		/*
		// Здесь поддержан элефан
		USE_ELEFUN=1;
		objSettings.sLikUser="******";
		objSettings.sLikKey=Recrypt("\xd3\x4c\xc3\x24\x84\x53\x3e\x2a\x2c\x21\x9e\x24\x48\x34\xb5\xb4");//"CCC2-HJ3S-88A6-C4TP";// EXECryptor_DecryptStr()?
		*/
	//}
	UpdateTrialityStatus(objSettings.sLikUser,objSettings.sLikKey);
	if(objSettings.iLikStatus<0){
		CSettings* objAntiDebug=0;
		objAntiDebug->ApplySettings();
		return FALSE;
	}
	CRYPT_END
	objSettings.Load();
	if(sConsoleMode=="help"){
		ShowHelp("Overview");
		return 0;
	}
	{// грузим ddown
		CBitmap bpTmp;
		bpTmp.LoadBitmap(IDB_DDOWN_A);
		_bmp().AddBmpRaw("DDOWN",&bpTmp,GetBitmapSize(bpTmp));
	}
	{// грузим remd
		CBitmap bpTmp;
		bpTmp.LoadBitmap(IDB_REMIND_A);
		_bmp().AddBmpRaw("REMINDER",&bpTmp,GetBitmapSize(bpTmp));
	}
	theApp.MainImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 0, 2);
	// Основные иконки
	AddBitmapToIList(theApp.MainImageList,IDB_IMAGELIST);
	for(int i=0;i<theApp.MainImageList.GetImageCount();i++){
		HICON hIcon=theApp.MainImageList.ExtractIcon(i);
		_bmp().AddBmp(_IL(i),hIcon);
		ClearIcon(hIcon);
	}
	_bmp().AddBmpRaw(IDB_BM_LOGO,CSize(LOGO_W,LOGO_H));
	// Пытаемся к пустому окну захимичится
	rFakedRect.SetRect(-10,0,0,0);
	LPCTSTR szClass = AfxRegisterWndClass(NULL);
	m_pFakeWnd = new CWnd;
	m_pFakeWnd->CreateEx(0, szClass, ROOT_WND_NAME, 0, rFakedRect, NULL, 0);
	m_pFakeWnd->ShowWindow(SW_HIDE);
	m_pFakeWnd->EnableWindow(FALSE);
	m_pFakeWnd->SetIcon(::AfxGetApp()->LoadIcon(MAIN_ICON),TRUE);
	m_pFakeWnd->SetIcon(::AfxGetApp()->LoadIcon(MAIN_ICON),FALSE);
	HotkeysSkipDD()=1;
	// Если при запуске небыло найдено ini-файла, показываем опции...
	if(objSettings.bStartWithOptions){
		objSettings.bStartWithOptions=FALSE;
		if(IsStartupWithWindows()==FALSE){
			StartupApplicationWithWindows(TRUE);
		}
		// точней больше не показываем
		// objSettings.OpenOptionsDialog();
	}
	
	// Создаем
	pMainDialogWindow = new AppMainDlg();
	pMainDialogWindowCrypt = pMainDialogWindow;
	if(!pMainDialogWindow){
		return FALSE;
	}
	theApp.m_pMainWnd=pMainDialogWindow;// Сначала задаем главное окно, потом создаем его
	pMainDialogWindow->Create(AppMainDlg::IDD,m_pFakeWnd);
	// Все!
	return TRUE;
}
Ejemplo n.º 5
0
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));
        }
    }
}