Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenchangenotify.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
1.7.6.1
|