ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

changenotify.cpp
Go to the documentation of this file.
00001 /*
00002  *    shell change notification
00003  *
00004  * Copyright 2000 Juergen Schmied
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <precomp.h>
00022 
00023 
00024 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00025 
00026 namespace
00027 {
00028     extern CRITICAL_SECTION SHELL32_ChangenotifyCS;
00029     CRITICAL_SECTION_DEBUG critsect_debug =
00030     {
00031         0, 0, &SHELL32_ChangenotifyCS,
00032         { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
00033           0, 0, { (DWORD_PTR)(__FILE__ ": SHELL32_ChangenotifyCS") }
00034     };
00035     CRITICAL_SECTION SHELL32_ChangenotifyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
00036 }
00037 
00038 typedef SHChangeNotifyEntry *LPNOTIFYREGISTER;
00039 
00040 /* internal list of notification clients (internal) */
00041 typedef struct _NOTIFICATIONLIST
00042 {
00043     struct _NOTIFICATIONLIST *next;
00044     struct _NOTIFICATIONLIST *prev;
00045     HWND hwnd;        /* window to notify */
00046     DWORD uMsg;        /* message to send */
00047     LPNOTIFYREGISTER apidl; /* array of entries to watch*/
00048     UINT cidl;        /* number of pidls in array */
00049     LONG wEventMask;    /* subscribed events */
00050     LONG wSignalledEvent;   /* event that occurred */
00051     DWORD dwFlags;        /* client flags */
00052     LPCITEMIDLIST pidlSignaled; /*pidl of the path that caused the signal*/
00053 
00054 } NOTIFICATIONLIST, *LPNOTIFICATIONLIST;
00055 
00056 static NOTIFICATIONLIST *head, *tail;
00057 
00058 #define SHCNE_NOITEMEVENTS ( \
00059    SHCNE_ASSOCCHANGED )
00060 
00061 #define SHCNE_ONEITEMEVENTS ( \
00062    SHCNE_ATTRIBUTES | SHCNE_CREATE | SHCNE_DELETE | SHCNE_DRIVEADD | \
00063    SHCNE_DRIVEADDGUI | SHCNE_DRIVEREMOVED | SHCNE_FREESPACE | \
00064    SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_MKDIR | \
00065    SHCNE_NETSHARE | SHCNE_NETUNSHARE | SHCNE_RMDIR | \
00066    SHCNE_SERVERDISCONNECT | SHCNE_UPDATEDIR | SHCNE_UPDATEIMAGE )
00067 
00068 #define SHCNE_TWOITEMEVENTS ( \
00069    SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_UPDATEITEM )
00070 
00071 /* for dumping events */
00072 static const char * DumpEvent( LONG event )
00073 {
00074     if( event == SHCNE_ALLEVENTS )
00075         return "SHCNE_ALLEVENTS";
00076 #define DUMPEV(x)  ,( event & SHCNE_##x )? #x " " : ""
00077     return wine_dbg_sprintf( "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
00078     DUMPEV(RENAMEITEM)
00079     DUMPEV(CREATE)
00080     DUMPEV(DELETE)
00081     DUMPEV(MKDIR)
00082     DUMPEV(RMDIR)
00083     DUMPEV(MEDIAINSERTED)
00084     DUMPEV(MEDIAREMOVED)
00085     DUMPEV(DRIVEREMOVED)
00086     DUMPEV(DRIVEADD)
00087     DUMPEV(NETSHARE)
00088     DUMPEV(NETUNSHARE)
00089     DUMPEV(ATTRIBUTES)
00090     DUMPEV(UPDATEDIR)
00091     DUMPEV(UPDATEITEM)
00092     DUMPEV(SERVERDISCONNECT)
00093     DUMPEV(UPDATEIMAGE)
00094     DUMPEV(DRIVEADDGUI)
00095     DUMPEV(RENAMEFOLDER)
00096     DUMPEV(FREESPACE)
00097     DUMPEV(EXTENDED_EVENT)
00098     DUMPEV(ASSOCCHANGED)
00099     DUMPEV(INTERRUPT)
00100     );
00101 #undef DUMPEV
00102 }
00103 
00104 static const char * NodeName(const NOTIFICATIONLIST *item)
00105 {
00106     const char *str;
00107     WCHAR path[MAX_PATH];
00108 
00109     if(SHGetPathFromIDListW(item->apidl[0].pidl, path ))
00110         str = wine_dbg_sprintf("%s", debugstr_w(path));
00111     else
00112         str = wine_dbg_sprintf("<not a disk file>" );
00113     return str;
00114 }
00115 
00116 static void AddNode(LPNOTIFICATIONLIST item)
00117 {
00118     TRACE("item %p\n", item );
00119 
00120     /* link items */
00121     item->prev = tail;
00122     item->next = NULL;
00123     if( tail )
00124         tail->next = item;
00125     else
00126         head = item;
00127     tail = item;
00128 }
00129 
00130 static LPNOTIFICATIONLIST FindNode( HANDLE hitem )
00131 {
00132     LPNOTIFICATIONLIST ptr;
00133     for( ptr = head; ptr; ptr = ptr->next )
00134         if( ptr == (LPNOTIFICATIONLIST) hitem )
00135             return ptr;
00136     return NULL;
00137 }
00138 
00139 static void DeleteNode(LPNOTIFICATIONLIST item)
00140 {
00141     UINT i;
00142 
00143     TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
00144 
00145     /* remove item from list */
00146     if( item->prev )
00147         item->prev->next = item->next;
00148     else
00149         head = item->next;
00150     if( item->next )
00151         item->next->prev = item->prev;
00152     else
00153         tail = item->prev;
00154 
00155     /* free the item */
00156     for (i=0; i<item->cidl; i++)
00157         SHFree((LPITEMIDLIST)item->apidl[i].pidl);
00158     SHFree(item->apidl);
00159     SHFree(item);
00160 }
00161 
00162 void InitChangeNotifications(void)
00163 {
00164 }
00165 
00166 void FreeChangeNotifications(void)
00167 {
00168     TRACE("\n");
00169 
00170     EnterCriticalSection(&SHELL32_ChangenotifyCS);
00171 
00172     while( head )
00173         DeleteNode( head );
00174 
00175     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
00176 
00177     // DeleteCriticalSection(&SHELL32_ChangenotifyCS); // static
00178 }
00179 
00180 /*************************************************************************
00181  * SHChangeNotifyRegister            [SHELL32.2]
00182  *
00183  */
00184 ULONG WINAPI
00185 SHChangeNotifyRegister(
00186     HWND hwnd,
00187     int fSources,
00188     LONG wEventMask,
00189     UINT uMsg,
00190     int cItems,
00191     SHChangeNotifyEntry *lpItems)
00192 {
00193     LPNOTIFICATIONLIST item;
00194     int i;
00195 
00196     item = (NOTIFICATIONLIST *)SHAlloc(sizeof(NOTIFICATIONLIST));
00197 
00198     TRACE("(%p,0x%08x,0x%08x,0x%08x,%d,%p) item=%p\n",
00199     hwnd, fSources, wEventMask, uMsg, cItems, lpItems, item);
00200 
00201     item->next = NULL;
00202     item->prev = NULL;
00203     item->cidl = cItems;
00204     item->apidl = (SHChangeNotifyEntry *)SHAlloc(sizeof(SHChangeNotifyEntry) * cItems);
00205     for(i=0;i<cItems;i++)
00206     {
00207         item->apidl[i].pidl = ILClone(lpItems[i].pidl);
00208         item->apidl[i].fRecursive = lpItems[i].fRecursive;
00209     }
00210     item->hwnd = hwnd;
00211     item->uMsg = uMsg;
00212     item->wEventMask = wEventMask;
00213     item->wSignalledEvent = 0;
00214     item->dwFlags = fSources;
00215 
00216     TRACE("new node: %s\n", NodeName( item ));
00217 
00218     EnterCriticalSection(&SHELL32_ChangenotifyCS);
00219 
00220     AddNode(item);
00221 
00222     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
00223 
00224     return (ULONG)item;
00225 }
00226 
00227 /*************************************************************************
00228  * SHChangeNotifyDeregister            [SHELL32.4]
00229  */
00230 BOOL WINAPI SHChangeNotifyDeregister(ULONG hNotify)
00231 {
00232     LPNOTIFICATIONLIST node;
00233 
00234     TRACE("(0x%08x)\n", hNotify);
00235 
00236     EnterCriticalSection(&SHELL32_ChangenotifyCS);
00237 
00238     node = FindNode((HANDLE)hNotify);
00239     if( node )
00240         DeleteNode(node);
00241 
00242     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
00243 
00244     return node?TRUE:FALSE;
00245 }
00246 
00247 /*************************************************************************
00248  * SHChangeNotifyUpdateEntryList               [SHELL32.5]
00249  */
00250 EXTERN_C BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
00251                   DWORD unknown3, DWORD unknown4)
00252 {
00253     FIXME("(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
00254           unknown1, unknown2, unknown3, unknown4);
00255 
00256     return -1;
00257 }
00258 
00259 static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL sub )
00260 {
00261     TRACE("%p %p %d\n", changed, watched, sub );
00262     if ( !watched )
00263         return FALSE;
00264     if (ILIsEqual( watched, changed ) )
00265         return TRUE;
00266     if( sub && ILIsParent( watched, changed, TRUE ) )
00267         return TRUE;
00268     return FALSE;
00269 }
00270 
00271 /*************************************************************************
00272  * SHChangeNotify                [SHELL32.@]
00273  */
00274 void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
00275 {
00276     LPCITEMIDLIST Pidls[2];
00277     LPNOTIFICATIONLIST ptr;
00278     UINT typeFlag = uFlags & SHCNF_TYPE;
00279 
00280     Pidls[0] = NULL;
00281     Pidls[1] = NULL;
00282 
00283     TRACE("(0x%08x,0x%08x,%p,%p):stub.\n", wEventId, uFlags, dwItem1, dwItem2);
00284 
00285     if( ( wEventId & SHCNE_NOITEMEVENTS ) && ( dwItem1 || dwItem2 ) )
00286     {
00287         TRACE("dwItem1 and dwItem2 are not zero, but should be\n");
00288         dwItem1 = 0;
00289         dwItem2 = 0;
00290         return;
00291     }
00292     else if( ( wEventId & SHCNE_ONEITEMEVENTS ) && dwItem2 )
00293     {
00294         TRACE("dwItem2 is not zero, but should be\n");
00295         dwItem2 = 0;
00296         return;
00297     }
00298 
00299     if( ( ( wEventId & SHCNE_NOITEMEVENTS ) &&
00300           ( wEventId & ~SHCNE_NOITEMEVENTS ) ) ||
00301         ( ( wEventId & SHCNE_ONEITEMEVENTS ) &&
00302           ( wEventId & ~SHCNE_ONEITEMEVENTS ) ) ||
00303         ( ( wEventId & SHCNE_TWOITEMEVENTS ) &&
00304           ( wEventId & ~SHCNE_TWOITEMEVENTS ) ) )
00305     {
00306         WARN("mutually incompatible events listed\n");
00307         return;
00308     }
00309 
00310     /* convert paths in IDLists*/
00311     switch (typeFlag)
00312     {
00313     case SHCNF_PATHA:
00314         if (dwItem1) Pidls[0] = SHSimpleIDListFromPathA((LPCSTR)dwItem1); //FIXME
00315         if (dwItem2) Pidls[1] = SHSimpleIDListFromPathA((LPCSTR)dwItem2); //FIXME
00316         break;
00317     case SHCNF_PATHW:
00318         if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW((LPCWSTR)dwItem1);
00319         if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW((LPCWSTR)dwItem2);
00320         break;
00321     case SHCNF_IDLIST:
00322         Pidls[0] = (LPCITEMIDLIST)dwItem1;
00323         Pidls[1] = (LPCITEMIDLIST)dwItem2;
00324         break;
00325     case SHCNF_PRINTERA:
00326     case SHCNF_PRINTERW:
00327         FIXME("SHChangeNotify with (uFlags & SHCNF_PRINTER)\n");
00328         return;
00329     case SHCNF_DWORD:
00330     default:
00331         FIXME("unknown type %08x\n",typeFlag);
00332         return;
00333     }
00334 
00335     {
00336         WCHAR path[MAX_PATH];
00337 
00338         if( Pidls[0] && SHGetPathFromIDListW(Pidls[0], path ))
00339             TRACE("notify %08x on item1 = %s\n", wEventId, debugstr_w(path));
00340 
00341         if( Pidls[1] && SHGetPathFromIDListW(Pidls[1], path ))
00342             TRACE("notify %08x on item2 = %s\n", wEventId, debugstr_w(path));
00343     }
00344 
00345     EnterCriticalSection(&SHELL32_ChangenotifyCS);
00346 
00347     /* loop through the list */
00348     for( ptr = head; ptr; ptr = ptr->next )
00349     {
00350         BOOL notify;
00351         DWORD i;
00352 
00353         notify = FALSE;
00354 
00355         TRACE("trying %p\n", ptr);
00356 
00357         for( i=0; (i<ptr->cidl) && !notify ; i++ )
00358         {
00359             LPCITEMIDLIST pidl = ptr->apidl[i].pidl;
00360             BOOL subtree = ptr->apidl[i].fRecursive;
00361 
00362             if (wEventId & ptr->wEventMask)
00363             {
00364                 if( !pidl )          /* all ? */
00365                     notify = TRUE;
00366                 else if( wEventId & SHCNE_NOITEMEVENTS )
00367                     notify = TRUE;
00368                 else if( wEventId & ( SHCNE_ONEITEMEVENTS | SHCNE_TWOITEMEVENTS ) )
00369                     notify = should_notify( Pidls[0], pidl, subtree );
00370                 else if( wEventId & SHCNE_TWOITEMEVENTS )
00371                     notify = should_notify( Pidls[1], pidl, subtree );
00372             }
00373         }
00374 
00375         if( !notify )
00376             continue;
00377 
00378         ptr->pidlSignaled = ILClone(Pidls[0]);
00379 
00380         TRACE("notifying %s, event %s(%x) before\n", NodeName( ptr ), DumpEvent(
00381                wEventId ),wEventId );
00382 
00383         ptr->wSignalledEvent |= wEventId;
00384 
00385         if (ptr->dwFlags  & SHCNRF_NewDelivery)
00386             SendMessageW(ptr->hwnd, ptr->uMsg, (WPARAM) ptr, (LPARAM) GetCurrentProcessId());
00387         else
00388             SendMessageW(ptr->hwnd, ptr->uMsg, (WPARAM)Pidls, wEventId);
00389 
00390         TRACE("notifying %s, event %s(%x) after\n", NodeName( ptr ), DumpEvent(
00391                 wEventId ),wEventId );
00392 
00393     }
00394     TRACE("notify Done\n");
00395     LeaveCriticalSection(&SHELL32_ChangenotifyCS);
00396 
00397     /* if we allocated it, free it. The ANSI flag is also set in its Unicode sibling. */
00398     if ((typeFlag & SHCNF_PATHA) || (typeFlag & SHCNF_PRINTERA))
00399     {
00400         SHFree((LPITEMIDLIST)Pidls[0]);
00401         SHFree((LPITEMIDLIST)Pidls[1]);
00402     }
00403 }
00404 
00405 /*************************************************************************
00406  * NTSHChangeNotifyRegister            [SHELL32.640]
00407  * NOTES
00408  *   Idlist is an array of structures and Count specifies how many items in the array.
00409  *   count should always be one when calling SHChangeNotifyRegister, or
00410  *   SHChangeNotifyDeregister will not work properly.
00411  */
00412 EXTERN_C ULONG WINAPI NTSHChangeNotifyRegister(
00413     HWND hwnd,
00414     int fSources,
00415     LONG fEvents,
00416     UINT msg,
00417     int count,
00418     SHChangeNotifyEntry *idlist)
00419 {
00420     return SHChangeNotifyRegister(hwnd, fSources | SHCNRF_NewDelivery,
00421                                   fEvents, msg, count, idlist);
00422 }
00423 
00424 /*************************************************************************
00425  * SHChangeNotification_Lock            [SHELL32.644]
00426  */
00427 HANDLE WINAPI SHChangeNotification_Lock(
00428     HANDLE hChange,
00429     DWORD dwProcessId,
00430     LPITEMIDLIST **lppidls,
00431     LPLONG lpwEventId)
00432 {
00433     DWORD i;
00434     LPNOTIFICATIONLIST node;
00435     LPCITEMIDLIST *idlist;
00436 
00437     TRACE("%p %08x %p %p\n", hChange, dwProcessId, lppidls, lpwEventId);
00438 
00439     /* EnterCriticalSection(&SHELL32_ChangenotifyCS); */
00440 
00441     node = FindNode( hChange );
00442     if( node )
00443     {
00444         idlist = (LPCITEMIDLIST *)SHAlloc( sizeof(LPCITEMIDLIST *) * node->cidl );
00445         for(i=0; i<node->cidl; i++)
00446             idlist[i] = (LPCITEMIDLIST)node->pidlSignaled;
00447         *lpwEventId = node->wSignalledEvent;
00448         *lppidls = (LPITEMIDLIST*)idlist;
00449         node->wSignalledEvent = 0;
00450     }
00451     else
00452         ERR("Couldn't find %p\n", hChange );
00453 
00454     /* LeaveCriticalSection(&SHELL32_ChangenotifyCS); */
00455 
00456     return (HANDLE) node;
00457 }
00458 
00459 /*************************************************************************
00460  * SHChangeNotification_Unlock            [SHELL32.645]
00461  */
00462 BOOL WINAPI SHChangeNotification_Unlock ( HANDLE hLock)
00463 {
00464     TRACE("\n");
00465     return 1;
00466 }
00467 
00468 /*************************************************************************
00469  * NTSHChangeNotifyDeregister            [SHELL32.641]
00470  */
00471 EXTERN_C DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1)
00472 {
00473     FIXME("(0x%08x):semi stub.\n",x1);
00474 
00475     return SHChangeNotifyDeregister( x1 );
00476 }

Generated on Fri May 25 2012 04:24:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.