Cleanup of code
[openwide.git] / openwidedll.c
blob46731b29aa30491321641513a3c6226c6978f3dc
1 /*
2 * Openwide -- control Windows common dialog
3 *
4 * Copyright (c) 2000 Luke Hudson
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 /* --- The following code comes from c:\lcc\lib\wizard\dll.tpl. */
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <shlwapi.h>
27 #include <shellapi.h>
28 #include <shlobj.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <dlgs.h>
32 #include "openwidedll.h"
33 #include "openwidedllres.h"
34 #include "owDllInc.h"
35 #include "owSharedUtil.h"
38 // DLL Instance handle
39 HINSTANCE ghInst = NULL;
41 // Handle to shared memory access locking mutex.
42 HANDLE ghMutex = NULL;
43 POWSharedData gpSharedMem = NULL; // pointer to shared mem
44 // Handle to filemapping for shared mem
45 HANDLE ghMap = NULL;
46 // System hook handles
47 HHOOK ghMsgHook = NULL, ghSysMsgHook = NULL;
49 // This cache is refreshed -- TODO: When?
50 OWSharedData gOwShared; // stores copy of shared mem for access to non-pointer datas without extended blocking
54 /* Add an icon to the toolbar within the O&S Dialogs
55 * @param hwTB -- toolbar handle
56 * @param hIcn -- icon handle
58 * @returns -1 on error, or the index of the new icon within the imagelist.
60 int addIcon2TB(HWND hwTB, HICON hIcn)
62 HIMAGELIST hImgList = NULL;
63 hImgList = (HIMAGELIST)SendMessage(hwTB, TB_GETIMAGELIST, 0, 0);
64 if (hImgList)
66 // int nImgs = ImageList_GetImageCount(hImgList);
67 int idxNew = ImageList_AddIcon(hImgList, hIcn);
68 if (idxNew == -1)
70 //dbg("%s, Error adding to imglist: %s", __func__, geterrmsg());
71 return -1;
73 else
75 //dbg("%s, Image added at index %d", __func__, idxNew);
76 SendMessage(hwTB, TB_SETIMAGELIST, 0, (LPARAM)hImgList);
77 return idxNew;
80 else
81 return -1;
85 * Adds a new button to the toolbar : hwnd
87 * @param hwnd -- parent window of toolbar, ie. the O&S Dialog.
89 * @returns 1 -- TODO: this should return 0 on error, but doesn't appear to.
91 static int addTBButton(HWND hwnd)
93 // Locate the toolbar handle.
94 HWND hwTB = findChildWindow(hwnd, CID_TOOLBAR, TOOLBARCLASSNAME);
96 // Create toolbar button structure
97 TBBUTTON tb = { 0 };
98 tb.iBitmap = VIEW_NETCONNECT;
100 // Load the toolbar icon, and add it to the imagelist, retaining the index.
101 int idxNew = -1;
102 HICON hIcn = (HICON)LoadImage(ghInst, MAKEINTRESOURCE(IDI_TBICON), IMAGE_ICON, 16, 16, 0);
103 if (hIcn)
105 idxNew = addIcon2TB(hwTB, hIcn);
106 DestroyIcon(hIcn);
108 if (idxNew >= 0)
109 tb.iBitmap = idxNew; // set button image index
110 tb.idCommand = OW_TBUTTON_CMDID; // set command id -- @see openwidedll.h
111 // Set the button style flags
112 tb.fsStyle = BTNS_AUTOSIZE | BTNS_BUTTON | BTNS_SHOWTEXT | BTNS_DROPDOWN; // BTNS_WHOLEDROPDOWN;
113 // Set the button state flags
114 tb.fsState = TBSTATE_ENABLED;
115 // And give it a tooltip ? TODO: Check this
116 tb.iString = (INT_PTR)"OpenWide by Lingo";
117 // Add the button.
118 SendMessage(hwTB, TB_ADDBUTTONS, 1, (LPARAM) & tb);
120 // Ensure that the toolbar window is large enough to show the new button.
121 RECT r;
122 int idxLast = SendMessage(hwTB, TB_BUTTONCOUNT, 0, 0) - 1;
123 if (SendMessage(hwTB, TB_GETITEMRECT, idxLast, (LPARAM) & r))
125 RECT rw;
126 GetWindowRect(hwTB, &rw);
127 MapWindowPoints(hwTB, NULL, (LPPOINT) & r, 2);
128 SetWindowPos(hwTB, NULL, 0, 0, (r.right + 8) - rw.left, rw.bottom - rw.top + 1, SWP_NOMOVE | SWP_NOZORDER);
130 return 1;
131 } // END of addTBButton(...)
134 * Show a drop-down menu from the toolbar button.
136 * @param hwnd -- O&S dialog
137 * @param hwTB -- toolbar handle
138 * @param uiItem -- id of toolbar item ? -- TODO: Check this.
140 static void dropMenu(HWND hwnd, HWND hwTB, UINT uiItem)
142 RECT r;
143 // Get the screen coords rectangle of the button
144 SendMessage(hwTB, TB_GETRECT, uiItem, (LPARAM) & r);
145 MapWindowPoints(hwTB, NULL, (LPPOINT) & r, 2);
147 // Set the area for the menu to avoid. ? :: TODO: see Platform SDK on TrackPopupMenuEx
148 TPMPARAMS tpm = { 0 };
149 tpm.cbSize = sizeof(tpm);
150 tpm.rcExclude = r;
152 // Create the menu structure.
153 HMENU hm = CreatePopupMenu();
154 AppendMenu(hm, MF_STRING, OW_EXPLORE_CMDID, "&Locate current folder with Explorer...");
155 AppendMenu(hm, MF_STRING, OW_SHOWDESK_CMDID, "Show &Desktop [for Gabriel]...");
156 AppendMenu(hm, MF_SEPARATOR | MF_DISABLED, 0, NULL);
157 AppendMenu(hm, MF_STRING, OW_ABOUT_CMDID, "&About OpenWide...");
158 SetMenuDefaultItem(hm, OW_SHOWDESK_CMDID, FALSE);
160 // * This section is todo with having Favourite directories, and is unfinished.
162 AppendMenu(hm, MF_STRING, OW_ADDFAV_CMDID, "Add &Favourite");
163 SetMenuDefaultItem(hm, OW_ADDFAV_CMDID, FALSE);
164 POWSharedData pow = lockSharedData();
165 if (pow)
167 dbg("%s, Locked shared data ok", __func__);
168 PFavLink pFav = pow->pFaves;
169 if (pFav)
171 MENUITEMINFO mii = { 0 };
172 mii.cbSize = sizeof(mii);
173 AppendMenu(hm, MF_SEPARATOR | MF_DISABLED, 0, NULL);
174 for (int i = 0; i < pow->nFaves; i++)
176 pFav = getNthFave(pow, i);
177 if (!pFav)
178 break;
179 static char szBuf[MAX_PATH + 8];
181 dbgLink("inserting...", pFav);
182 mii.fMask = MIIM_STRING | MIIM_DATA | MIIM_ID;
183 mii.fType = MFT_STRING;
184 wsprintf(szBuf, "%s\tCtrl+%d", pFav->szFav, (pFav->idCmd - OW_FAVOURITE_CMDID) + 1);
185 mii.dwTypeData = szBuf;
186 mii.dwItemData = pFav->idCmd;
187 mii.wID = pFav->idCmd;
189 int iRes = InsertMenuItem(hm, -1, TRUE, &mii);
190 if (iRes == 0)
191 dbg("%s, Failed inserting item: %s", __func__, geterrmsg());
192 //idx = AppendMenu(hm, MF_STRING, iCmd++, pFav->szFav);
195 unlockSharedData(pow);
198 // Display, track, then destroy the menu.
199 TrackPopupMenuEx(hm, TPM_HORIZONTAL | TPM_RIGHTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, r.right, r.bottom, hwnd, &tpm);
200 DestroyMenu(hm);
201 } // END of dropMenu(...)
205 // add a new 'place' into the Places bar.
206 int addPlace(HWND hwnd, PFavLink plk)
208 HWND hwTB = GetDlgItem(hwnd, CID_PLACES);
210 TBBUTTON tb = { 0 };
211 tb.iBitmap = giPlacesIcon;
212 tb.idCommand = plk->idCmd;
213 tb.fsStyle = BTNS_BUTTON | BTNS_SHOWTEXT; // BTNS_WHOLEDROPDOWN;
214 tb.fsState = TBSTATE_ENABLED;
215 tb.iString = (INT_PTR)PathFindFileName(plk->szFav);
216 SendMessage(hwTB, TB_ADDBUTTONS, 1, (LPARAM) & tb);
217 return 1;
221 // Add a new favourite dir, first retrieving the path from the current view of the O&S dialog.
222 // *unfinished*
223 int addFavourite(HWND hwnd)
225 //static char szBuf[2*MAX_PATH+1];
226 assert( IsWindow(hwnd));
228 char *szBuf = (char *)GlobalAlloc(GPTR, 2 * MAX_PATH + 1);
229 if( !szBuf )
230 return 0;
231 if( SendMessage(hwnd, CDM_GETFOLDERPATH, 2*MAX_PATH, (LPARAM)szBuf) > 0 )
233 if( !faveExists(szBuf) )
235 PFavLink plNew = newFav(szBuf);
236 if( plNew )
237 addPlace(hwnd, plNew);
238 else
239 dbg("%s, failed to create new fave", __func__);
241 else
242 dbg("%s, Fave: '%s' exists already", __func__, szBuf);
243 return 1;
245 GlobalFree(szBuf);
246 return 0;
251 * Given the handle to the O&S dialog, this does the magic to it, such as
252 * adding toolbar buttons, setting the focus and view mode, and adding items to
253 * the system menu.
255 * @returns 1, TODO:: There should be error indication, perhaps!
257 int openWide(HWND hwnd)
259 // set placement
260 int w = gOwShared.szDim.cx;
261 int h = gOwShared.szDim.cy;
262 int x = gOwShared.ptOrg.x;
263 int y = gOwShared.ptOrg.y;
264 SetWindowPos(hwnd, NULL, x, y, w, h, SWP_NOZORDER);
266 // set view mode
267 HWND hwDirCtl = GetDlgItem(hwnd, CID_DIRLISTPARENT);
268 WORD vCmdID = viewToCmdID(gOwShared.iView);
269 // set the view mode, by sending a fake command message.
270 SendMessage(hwDirCtl, WM_COMMAND, MAKEWPARAM(vCmdID, 0), 0);
272 // set the focus!
273 focusDlgItem(hwnd, gOwShared.iFocus);
275 #ifdef HOOK_SYSMSG
276 // debug hook, to find menu cmd IDs
277 dbg("Hooking SYSMSG...");
278 ghSysMsgHook = SetWindowsHookEx(
279 WH_SYSMSGFILTER,
280 SysMsgProc,
281 ghInst,
282 0 //GetCurrentThreadId() // Only install for THIS thread!!!
284 dbg("Hooking returned %p", ghSysMsgHook);
285 #endif
286 // Allow drag&drop onto window. Unfortunately this doesn't work for the
287 // directory list, as that is already set to accept drops, as a command to
288 // copy/move files. I would have to subclass this too, and that's rather
289 // more complicated.
290 DragAcceptFiles(hwnd, TRUE);
292 // Insert item into the system menu (right-click on titlebar)
293 HMENU hm = GetSystemMenu(hwnd, FALSE);
294 AppendMenu(hm, MF_SEPARATOR | MF_DISABLED, 0, NULL);
295 AppendMenu(hm, MF_STRING, OW_EXPLORE_CMDID, "&Locate current folder with Explorer...");
296 AppendMenu(hm, MF_STRING, OW_ABOUT_CMDID, "&About OpenWide...");
298 addTBButton(hwnd); // add the toolbar button.
300 // Modify the dir-list view flags
301 HWND hwShellCtl = GetDlgItem(hwnd, CID_DIRLISTPARENT);
302 hwShellCtl = GetDlgItem(hwShellCtl, 1);
303 ListView_SetExtendedListViewStyleEx(hwShellCtl, OW_LISTVIEW_STYLE, OW_LISTVIEW_STYLE );
305 return 1;
306 } // END openWide(...)
309 /* Load the desktop folder into the dir list */
310 void showDesktop(HWND hwnd)
312 char * szDesk = GlobalAlloc(GPTR, MAX_PATH+1);
313 if( szDesk && SHGetSpecialFolderPath(hwnd, szDesk, CSIDL_DESKTOPDIRECTORY,FALSE) )
315 char *szOld = getDlgItemText(hwnd, CID_FNAME);
316 SetDlgItemText(hwnd, CID_FNAME, szDesk);
317 SendDlgItemMessage(hwnd, CID_FNAME, EM_SETSEL, -1, -1);
318 SendDlgItemMessage(hwnd, CID_FNAME, EM_REPLACESEL, FALSE, (LPARAM)"\\");
319 SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDOK));
320 if( szOld )
321 SetDlgItemText(hwnd, CID_FNAME, szOld);
322 else
323 SetDlgItemText(hwnd, CID_FNAME, "");
324 free(szOld);
325 GlobalFree(szDesk);
327 } // END showDesktop
331 * This is the callback for the subclassed O&S dialog window, and it handles
332 * all the extra functionality, passing along messages to the old callback
333 * function unless the behaviour is modified.
336 LRESULT CALLBACK WINAPI wpSubMain(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
338 /* if( gbDbg )
340 dbgWM(hwnd, msg, wp, lp);
343 // retrieve a ptr to the extra information associated with the window.
344 POWSubClassData pow = (POWSubClassData)GetProp(hwnd, OW_PROP_NAME);
345 if( !pow )
346 return DefWindowProc(hwnd, msg, wp, lp); // something's broken, so just allow default window function.
348 static char buffer[MAX_PATH+1];
350 switch(msg)
352 case WM_INITDIALOG:
354 // dbg("DLL: INITDIALOG");
355 LRESULT lRes = CallWindowProc(pow->wpOrig, hwnd, msg, wp, lp); // call the old callback
356 ShowWindow(hwnd, SW_HIDE); // hide the window, until it's been magick-ed by openWide(...)
357 return lRes;
359 break;
361 case WM_SHOWWINDOW:
362 if( wp && !pow->bSet ) // catch the first SHOWWINDOW only,
364 pow->bSet = TRUE;
365 openWide(hwnd);
367 break;
369 case WM_COMMAND: // handle custom toolbar button commands, etc.
370 switch (LOWORD(wp))
372 case OW_ABOUT_CMDID: // about
373 MessageBox(hwnd, "OpenWide is written by Luke Hudson. (c)2005", "About OpenWide", MB_OK);
374 return 0;
375 // show desktop item, or click on button rather than
376 // dropdown (ie, defaults to show desktop menuitem)
377 case OW_TBUTTON_CMDID:
378 case OW_SHOWDESK_CMDID:
379 showDesktop(hwnd);
380 break;
381 case OW_EXPLORE_CMDID: // Explore current dir in new Explorer window
383 // Build a command line
384 char *szParm = "/select,";
385 wsprintf(buffer, szParm);
386 int len = strlen(szParm);
387 LPARAM lpBuf = (LPARAM)buffer + (LPARAM)len;
388 //dbg("CDM_GET..PATH, cbSize=%d, buffer = %p", MAX_PATH-len, lpBuf);
389 len = SendMessage(hwnd, CDM_GETFOLDERPATH, MAX_PATH - len, lpBuf); //(LPARAM)(char *)((unsigned int)buffer + (unsigned int)len));
390 if (len)
392 // execute the command line
393 ShellExecute(hwnd, NULL, "explorer.exe", buffer, NULL, SW_SHOWNORMAL);
395 } // case
396 return 0;
398 // Handling of favourites -- UNFININSHED
399 case OW_ADDFAV_CMDID:
400 doAddFave(hwnd);
401 return 0;
402 default:
403 if (LOWORD(wp) >= OW_FAVOURITE_CMDID)
405 getFavourite(hwnd, (int)LOWORD(wp));
407 break;*/
408 } // switch : command ids
409 break;
411 // Handle notifications from the toolbar
412 case WM_NOTIFY:
414 NMHDR *phdr = (NMHDR *)lp;
415 HWND hwTB = findChildWindow(hwnd, CID_TOOLBAR, TOOLBARCLASSNAME);
416 if (phdr->hwndFrom == hwTB)
418 // dbg("Got notify %d from toolbar", phdr->code);
419 if (phdr->code == TBN_DROPDOWN)
421 NMTOOLBAR *ptb = (NMTOOLBAR *)lp;
422 if (ptb->iItem == OW_TBUTTON_CMDID)
424 dropMenu(hwnd, hwTB, ptb->iItem);
425 return TBDDRET_DEFAULT;
430 break;
432 // handle notifications from the dir listview control
433 case WM_PARENTNOTIFY:
434 if( LOWORD(wp) == WM_CREATE)
436 static char buf[33];
437 GetClassName((HWND)lp, buf, 32);
439 if( strcmp(buf, "SHELLDLL_DefView") == 0 )
441 // dbg("Shell defview ctl created");
442 // subclass((HWND)lp, wpSubShellCtl, (LPARAM)hwnd);
443 HWND hwLV = GetDlgItem((HWND)lp, 1);
444 if( hwLV )
446 if( GetWindowLong(hwLV, GWL_STYLE) & LVS_REPORT ) // if details view is in effect.
448 // update style flags
449 ListView_SetExtendedListViewStyleEx(hwLV, OW_LISTVIEW_STYLE, OW_LISTVIEW_STYLE );
450 // Send Control+NumpadPlus to expand all the columns to fit contents
451 INPUT in[4] = {0};
452 in[0].type = INPUT_KEYBOARD;
453 in[0].ki.wVk = VK_CONTROL;
454 in[1].type = INPUT_KEYBOARD;
455 in[1].ki.wVk = VK_ADD;
456 in[2].type = INPUT_KEYBOARD;
457 in[2].ki.wVk = VK_CONTROL;
458 in[2].ki.dwFlags = KEYEVENTF_KEYUP;
459 in[3].type = INPUT_KEYBOARD;
460 in[3].ki.wVk = VK_ADD;
461 in[3].ki.dwFlags = KEYEVENTF_KEYUP;
462 HWND hwOld = SetFocus(hwLV);
463 SendInput(4, in, sizeof(INPUT));
464 SetFocus(hwOld);
467 //SetTimer(hwnd, 251177, 1, NULL); // set a timer, for what? TODO:: Check this
470 break;
471 /// Deprecated -- I think? TODO: Check
472 /* case WM_TIMER:
473 if( wp == 251177 )
475 KillTimer(hwnd, 251177);
476 HWND hwDirCtl = GetDlgItem(hwnd, CID_DIRLISTPARENT);
477 if( getSharedData() )
479 if( gOwShared.iView == V_THUMBS || gOwShared.iView == V_TILES )
481 // dbg("posting cmd message to reset view?");
482 WORD vCmdID = viewToCmdID(gOwShared.iView);
483 PostMessage(hwDirCtl, WM_COMMAND, MAKEWPARAM(vCmdID, 0), 0);
487 break;
489 case WM_SYSCOMMAND: // Handle system menu commands
491 int cmdId = wp & 0xFFF0;
492 if( cmdId == OW_ABOUT_CMDID )
494 MessageBox(hwnd, "OpenWide is written by Luke Hudson. (c)2005", "About OpenWide", MB_OK);
495 return 0;
497 else if( cmdId == OW_EXPLORE_CMDID )
499 char * szParm = "/select,";
500 wsprintf(buffer, szParm);
501 int len = strlen(szParm);
502 len = SendMessage(hwnd, CDM_GETFOLDERPATH, MAX_PATH-len, (LPARAM)(buffer+len));
503 if( len )
505 ShellExecute(hwnd, NULL, "explorer.exe", buffer, NULL, SW_SHOWNORMAL);
509 break;
510 /* case WM_NCPAINT: // handle painting of non-content area, ie. window titlebar and frame.
512 HDC hdc = GetWindowDC(hwnd);
513 HBRUSH hbrOld;
514 HPEN hpOld;
515 hbrOld = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
516 hpOld = SelectObject(hdc, GetStockObject(NULL_PEN));
517 RECT r;
518 GetWindowRect(hwnd, &r);
519 r.right-=r.left;
520 r.left -= r.left;
521 r.bottom-=r.top;
522 r.top -= r.top;
523 RoundRect(hdc, r.left, r.top, r.right, r.bottom, 16,16);
524 SelectObject(hdc, hbrOld);
525 SelectObject(hdc, hpOld);
526 ReleaseDC(hwnd, hdc);
528 break;*/
529 case WM_DROPFILES: // Handle files which are dragged&dropped onto window.
531 HANDLE hDrop = (HANDLE)wp;
532 int nFiles = DragQueryFile(hDrop, (UINT)-1, NULL, 0);
533 if( nFiles == 1 )
535 if( DragQueryFile(hDrop, 0, buffer, MAX_PATH) )
537 if( PathIsDirectory(buffer) )
539 // Set the view to dropped directory path.
540 SetDlgItemText(hwnd, CID_FNAME, buffer);
541 SendDlgItemMessage(hwnd, CID_FNAME, EM_SETSEL, -1, -1);
542 SendDlgItemMessage(hwnd, CID_FNAME, EM_REPLACESEL, FALSE, (LPARAM)"\\");
543 SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDOK));
544 SetDlgItemText(hwnd, CID_FNAME, "");
545 if( getSharedData() )
547 focusDlgItem(hwnd, gOwShared.iFocus);
553 return 0;
554 case WM_DESTROY:
556 //dbg("DLL: DESTROY");
557 if( openSharedMem() )
559 //dbg("DLL: Opened shared memory");
560 if( --gpSharedMem->refCount < 0 ) // Update the count for number of users of subclass code
561 gpSharedMem->refCount = 0;
562 //dbg("DLL: dec'd refCount to %d, posting msg %x to app window %p", gpSharedMem->refCount,
563 // gpSharedMem->iCloseMsg, gpSharedMem->hwListener);
565 // Notify application that another O&S dialog has closed
566 PostMessage( gpSharedMem->hwListener, gpSharedMem->iCloseMsg, 0,0);
567 // Release any hold on the shared memory.
568 closeSharedMem();
570 // Remove subclassing
571 WNDPROC wpOrig = pow->wpOrig;
572 unsubclass(hwnd);
573 // Call original WM_DESTROY
574 return CallWindowProc(wpOrig, hwnd, msg, wp, lp);
576 break;
578 return CallWindowProc(pow->wpOrig, hwnd, msg, wp, lp);
579 } // END wpSubMain
582 // Subclass the listview control -- TODO: I think this is un-needed
583 LRESULT CALLBACK WINAPI wpSubShellCtl(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
585 POWSubClassData pow = (POWSubClassData)GetProp(hwnd, OW_PROP_NAME);
586 if( !pow )
587 return DefWindowProc(hwnd, msg, wp, lp);
589 switch(msg)
591 case WM_DROPFILES:
593 HANDLE hDrop = (HANDLE)wp;
594 int nFiles = DragQueryFile(hDrop, (UINT)-1, NULL, 0);
595 ////dbg("%d files dropped, fwding mesg to %p", nFiles, pow->lpData);
596 return SendMessage((HWND)pow->lpData, msg, wp, lp);
598 break;
599 case WM_DESTROY:
601 WNDPROC wpOrig = pow->wpOrig;
602 unsubclass(hwnd);
603 //dbg("SHell view being destroyed");
604 return CallWindowProc(wpOrig, hwnd, msg, wp, lp);
606 break;
608 return CallWindowProc(pow->wpOrig, hwnd, msg, wp, lp);
609 } // END wpSubShellCtl
612 /* Check whether this application has been excluded, ie, whether we should not
613 * mess with its O&S dialogs
615 static BOOL isExcluded(const char *szApp)
617 BOOL bEx = FALSE;
618 HKEY hk = regOpenKey(HKEY_CURRENT_USER, OW_REGKEY_EXCLUDES_NAME);
619 if( hk )
621 regGetDWORD(hk, szApp, &bEx);
622 regCloseKey(hk);
624 return bEx;
629 * Investigate the WM_CREATEPARAMS message
631 static void dbgCreateParams(LPVOID lpCreateParams)
633 UNALIGNED short * pcbData = (UNALIGNED short *)lpCreateParams;
634 if( pcbData )
636 short cbData = * pcbData;
637 UNALIGNED byte *pbData = (UNALIGNED byte *)pcbData;
638 pbData += sizeof(short);
639 dbg("**CreateParams:");
640 dbg(" %d bytes of data, starting at x%p", cbData, pbData);
641 if( pbData )
643 dbg(" First 8 bytes follow:");
644 int len = min( cbData, 8 );
645 char s[32] = {0};
646 int i;
647 for(i=0; i < len; i++)
649 s[i] = pbData[i];
651 s[i] = 0;
652 dbg(" \"%s\" (hex follows)", s);
653 char st[8];
654 s[0] = 0;
655 for(i=0; i < len; i++)
657 sprintf(st, "%02x ", pbData[i]);
658 strcat(s, st);
660 dbg(" %s", s);
663 else
664 dbg("CreateParams is NULL (%p)", pcbData);
669 * This is the main hook callback, which watches window creation, and
670 * subclasses those which appear (with luck, correctly) to be O&S dialogs */
671 static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
674 if(nCode < 0)
676 if( ghMsgHook )
677 return CallNextHookEx(ghMsgHook, nCode, wParam, lParam);
680 switch(nCode)
682 case HCBT_CREATEWND:
684 static char buf[256];
685 HWND hwNew = (HWND)wParam;
686 CBT_CREATEWND * pcw = (CBT_CREATEWND *)lParam;
687 CREATESTRUCT * pcs = (CREATESTRUCT*) pcw->lpcs;
689 if( GetClassName(hwNew, buf, 255) && pcs->lpszName )
691 DWORD style = (DWORD)GetWindowLong(hwNew, GWL_STYLE);
692 DWORD exStyle = (DWORD)GetWindowLong(hwNew, GWL_EXSTYLE);
694 if( style == OW_MATCH_STYLE && exStyle == OW_MATCH_EXSTYLE
695 && strcmp(buf, "#32770") == 0
696 && strcmp(pcs->lpszName, "Open") == 0 )
698 BOOL bTakeOver = TRUE;
700 //// FIND name of Calling app ////
701 char *szApp = malloc( MAX_PATH+1 );
702 if( szApp && GetModuleFileName(NULL, szApp, MAX_PATH) )
704 if( isExcluded(szApp) )
705 bTakeOver = FALSE;
706 //dbg("DLL: Module: %s", szApp);
707 free(szApp);
710 ///dbg("DLL: Found O&S dlg %p, attempting access to shared mem", hwNew);
712 if( bTakeOver && openSharedMem() )
714 //dbgCreateParams(pcs->lpCreateParams);
715 //dbg("DLL: Opened shared memory");
716 if( gpSharedMem->bDisable )
717 bTakeOver = FALSE;
718 else
719 gpSharedMem->refCount++;
720 //dbg("DLL: Inc'd refCount to %d", gpSharedMem->refCount);
721 closeSharedMem();
722 //dbg("DLL: Closed shared memory");
724 if( bTakeOver )
726 pcs->style &= ~WS_VISIBLE;
727 ShowWindow(hwNew, SW_HIDE);
728 subclass(hwNew, wpSubMain, 0);
733 return 0;
735 // Call the next hook, if there is one
736 return CallNextHookEx(ghMsgHook, nCode, wParam, lParam);
737 } // END CBTProc
740 * Access to shared memory, and copy data to cache
742 int openSharedMem(void)
744 if( ghMap != NULL || gpSharedMem != NULL )
745 return 1;
747 if(!waitForMutex())
748 return 0;
750 ghMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, OW_SHARED_FILE_MAPPING);
751 if( ghMap )
753 gpSharedMem = (POWSharedData)MapViewOfFile(ghMap, FILE_MAP_WRITE, 0,0, 0);
754 if( gpSharedMem )
756 CopyMemory(&gOwShared, gpSharedMem, sizeof(OWSharedData));
757 return 1;
759 else
760 closeSharedMem();
762 return 0;
763 } // END openSharedMem
766 * Release any access to shared memory we may hold.
768 void closeSharedMem(void)
770 if( gpSharedMem )
772 UnmapViewOfFile(gpSharedMem);
773 gpSharedMem = NULL;
775 if( ghMap )
777 CloseHandle(ghMap);
778 ghMap = NULL;
780 releaseMutex();
781 } // END closeSharedMem
785 * Simply refreshes our cache of the shared data.
786 * Use this as a preference to the open/close-SharedMem functions.
788 * @returns 1 if successful, 0 on error.
790 int getSharedData(void)
792 int rv = 0;
793 if( openSharedMem() )
795 rv = 1;
796 closeSharedMem();
798 return rv;
803 * exported function to setup the CBT hook, which watches window creation.
805 int DLLEXPORT setHook(void)
807 if(ghMsgHook != NULL)
809 //SendMessage(gOwShared.hwLog, LB_ADDSTRING, 0, (LPARAM)"Already hooked");
810 return 1;
812 if(!getSharedData())
814 // SendMessage(hwLB, LB_ADDSTRING, 0, (LPARAM)"Failed to get shared data!!!");
815 // dbg("Hook failed to get shared mems");
816 return FALSE;
818 //SendMessage(gOwShared.hwLog, LB_ADDSTRING, 0, (LPARAM)"Setting hook....");
819 ghMsgHook = SetWindowsHookEx(WH_CBT, CBTProc, ghInst, 0);
820 if(ghMsgHook != NULL)
822 //dbg("Hooked okay");
823 //SendMessage(gOwShared.hwLog, LB_ADDSTRING, 0, (LPARAM)"Hooked ok!");
824 return 1;
826 //dbg("Hook failed");
827 //SendMessage(gOwShared.hwLog, LB_ADDSTRING, 0, (LPARAM)"Failed hook");
828 return 0;
833 * Exported function to remove the CBT hook.
835 int DLLEXPORT rmvHook(void)
837 if( !ghMsgHook )
838 return 1;
840 if( ghSysMsgHook )
842 UnhookWindowsHookEx(ghSysMsgHook);
843 ghSysMsgHook = NULL;
845 //dbg("DLL: Removing hook");
846 if( ghMsgHook )
848 UnhookWindowsHookEx(ghMsgHook);
849 ghMsgHook = NULL;
851 //dbg("DLL: removed hook okay");
852 return 1;
858 // This callback handles SYSMSG hooks, which I have used to investigate the O&S dialog behaviour.
860 static LRESULT CALLBACK SysMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
862 HWND hwnd;
864 if(nCode < 0)
865 return CallNextHookEx(ghMsgHook, nCode, wParam, lParam);
867 LPMSG pMsg = (MSG *)lParam;
868 if( pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST )
870 dbg("SysMsgProc: %d is code, pMsg: hwnd: %p, message: %d, wp: %x, lp: %x", nCode, pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam);
872 if( GetAsyncKeyState(VK_SHIFT) & 0x8000 )
874 LRESULT lRet = CallNextHookEx(ghSysMsgHook, nCode, wParam, lParam);
875 UnhookWindowsHookEx(ghSysMsgHook);
876 ghSysMsgHook = NULL;
877 return lRet;
879 switch(pMsg->message)
881 case WM_MENUSELECT:
883 dbg("WM_MENUSELECT: %p %d", pMsg->hwnd, LOWORD(pMsg->wParam));
885 HMENU hm = (HMENU)pMsg->lParam;
886 if(hm)
888 static char buf[80];
889 MENUITEMINFO mii ={0};
890 int nItems = GetMenuItemCount(hm);
891 dbg(" %d items in menu", nItems);
892 for(int i=0; i < nItems; i++)
894 mii.cbSize = sizeof(mii);
895 mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
896 mii.cch = 79;
897 mii.dwTypeData = (LPTSTR)buf;
898 GetMenuItemInfo(hm, i, TRUE, &mii);
899 dbg(" Item %d: %.8s, %d", i, buf, mii.wID);
903 UnhookWindowsHookEx(ghSysMsgHook);
904 ghSysMsgHook = NULL;
906 break;
907 default:
908 break;
910 // Call the next hook, if there is one
911 return CallNextHookEx(ghSysMsgHook, nCode, wParam, lParam);
918 * Main DLL entry point
920 BOOL DLLEXPORT WINAPI DLLPROC(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
922 switch (fdwReason)
924 case DLL_PROCESS_ATTACH:
925 ghInst = hDLLInst;
926 break;
927 case DLL_PROCESS_DETACH:
928 ghInst = NULL;
929 break;
930 default:
931 break;
933 return TRUE;