Index: trunk/src/kernel/qapplication_pm.cpp
===================================================================
--- trunk/src/kernel/qapplication_pm.cpp	(revision 151)
+++ trunk/src/kernel/qapplication_pm.cpp	(revision 153)
@@ -1799,5 +1799,5 @@
                 // get the modal widget that made this window blocked
                 QWidget *m =
-                    (QWidget*) WinQueryWindowULong( widget->winId(), QWL_QTMODAL );
+                    (QWidget*) WinQueryWindowPtr( widget->winId(), QWL_QTMODAL );
                 if( m ) {
                     if ( swp.fl & SWP_ACTIVATE ) {
@@ -1970,5 +1970,5 @@
             }
             QWidget *blockedBy =
-                (QWidget*) WinQueryWindowULong( w->winId(), QWL_QTMODAL );
+                (QWidget*) WinQueryWindowPtr( w->winId(), QWL_QTMODAL );
             if ( blocked ) {
                 // stop sending on alreay blocked widgets
@@ -1980,6 +1980,5 @@
                     return;
             }
-            WinSetWindowULong( w->winId(), QWL_QTMODAL,
-                    blocked ? (ULONG) modal : 0 );
+            WinSetWindowPtr( w->winId(), QWL_QTMODAL, blocked ? modal : NULL );
             WinEnableWindow( w->winFId(), !blocked );
         }
@@ -1993,5 +1992,5 @@
         while( ( o = it.current() ) != 0 ) {
             ++it;
-            qt_sendBlocked( o, modal, e, FALSE );
+            qt_sendBlocked( o, modal, e, blocked ? FALSE : TRUE );
         }
     }
@@ -2017,4 +2016,25 @@
     QEvent e( blocked ? QEvent::WindowBlocked : QEvent::WindowUnblocked );
 
+    if ( !blocked ) {
+        // For unblocking, we go through all top-level widgets and unblock
+        // those that have been blocked by the given modal widget. It means that
+        // we don't select widgets to unblock based on widget flags (as we do
+        // below when blocking) because these flags might have been changed
+        // so that we could skip widgets that we would have to unblock. Although
+        // normally widget flags should never be changed after widget creation
+        // (except that by QWidget::reparentSys() that takes blocking into
+        // account and corrects it as needed), nothing stops one from doing so,
+        // leading to a case when the QWL_QTMODAL word of some widget still
+        // points to a widget that has been deleted (so that any attempt to
+        // access it results into a nasty segfault).
+        QWidgetList *list = QApplication::topLevelWidgets();
+        for( QWidget *w = list->first(); w; w = list->next() ) {
+            if ( WinQueryWindowPtr( w->winId(), QWL_QTMODAL ) == modal )
+                qt_sendBlocked( w, modal, &e, TRUE );
+        }
+        delete list;
+        return;
+    }
+    
     // find the modal's group leader
     QWidget *mgl = modal->parentWidget();
@@ -2030,5 +2050,5 @@
     for( QWidget *w = list->first(); w; w = list->next() ) {
         if (
-            !w->isDesktop() && !w->isPopup() && !w->isHidden() &&
+            !w->isDesktop() && !w->isPopup() &&
             !w->testWFlags( Qt::WGroupLeader ) &&
             (!w->parentWidget() || w->parentWidget()->isDesktop())
@@ -2045,5 +2065,5 @@
     // qt_tryModalHelper() also assumes that the toppest modal widget blocks
     // other modals, regardless of WGroupLeader flags in parents. do the same.
-    // note: the given modal is not yet at the stack here.
+    // Note: the given modal is not yet at the stack here.
     if ( qt_modal_stack ) {
         QWidget *m = qt_modal_stack->first();
Index: trunk/src/kernel/qwidget_pm.cpp
===================================================================
--- trunk/src/kernel/qwidget_pm.cpp	(revision 151)
+++ trunk/src/kernel/qwidget_pm.cpp	(revision 153)
@@ -941,4 +941,9 @@
 */
 
+        // strictly speaking, PM is not obliged to initialize window data
+        // with zeroes (although seems to), so do it ourselves
+        for ( LONG i = 0; i <= QT_EXTRAWINDATASIZE - 4; i += 4 )
+            WinSetWindowULong( id, i, 0 );
+
         // When the FS_SHELLPOSITION flag is specified during WC_FRAME window
         // creation its size and position remains zero until it is shown
@@ -1083,7 +1088,7 @@
     QWidget *blockedBy = 0;
     if ( isTopLevel() )
-        blockedBy = (QWidget*) WinQueryWindowULong( winId(), QWL_QTMODAL );
+        blockedBy = (QWidget*) WinQueryWindowPtr( winId(), QWL_QTMODAL );
     if ( !blockedBy && parentWidget() )
-        blockedBy = (QWidget*) WinQueryWindowULong(
+        blockedBy = (QWidget*) WinQueryWindowPtr(
             parentWidget()->topLevelWidget()->winId(), QWL_QTMODAL );
     if ( blockedBy ) {
@@ -1151,5 +1156,5 @@
     blockedBy = 0;
     if ( parentWidget() )
-        blockedBy = (QWidget*) WinQueryWindowULong(
+        blockedBy = (QWidget*) WinQueryWindowPtr(
             parentWidget()->topLevelWidget()->winId(), QWL_QTMODAL );
     if ( blockedBy ) {
