Release/: Updated readme.txt and added gpl-2.0.txt
[openwide.git] / openwide.c
blob5a83a92cb5d2a3a0983f8ea546d81629044cbcff
1 #include <windows.h>
2 /**
3 * @author Luke Hudson
4 * @licence GPL2
5 */
7 #include <objbase.h>
8 #include <shobjidl.h>
9 #include <shlguid.h>
10 #include <shlobj.h>
11 #include <shlwapi.h>
12 #include <shellapi.h>
13 #include <stdio.h>
14 #include "openwidedll.h"
15 #include "openwideres.h"
16 #include "owutil.h"
17 #include "owSharedUtil.h"
18 #include "openwide_proto.h"
21 enum TrayCommands { IDM_ABOUT = 100, IDM_SETTINGS, IDM_QUIT };
23 HWND ghwMain = NULL, ghwPropSheet = NULL;
24 HINSTANCE ghInstance = NULL;
25 //HWND ghwListBox = NULL;
27 HICON ghIconLG = NULL, ghIconSm = NULL;
29 POWSharedData gPowData = NULL;
30 HANDLE ghSharedMem = NULL;
31 HANDLE ghMutex = NULL;
32 UINT giCloseMessage = 0;
34 int initSharedMem(HWND hwnd)
36 int rVal = 0;
37 ghMutex = CreateMutex(NULL, TRUE, OW_MUTEX_NAME);
38 if( !ghMutex )
39 return 0;
40 /* else if( GetLastError() == ERROR_ALREADY_EXISTS)
42 CloseHandle(ghMutex);
43 ghMutex = NULL;
44 return 0;
45 }*/
46 POWSharedData pRData = NULL;
47 // try to read in saved settings from registry
48 HKEY hk = regCreateKey(HKEY_CURRENT_USER, OW_REGKEY_NAME);
49 if( hk )
51 BOOL bOK;
52 DWORD dwSize = regReadDWORD(hk, NULL, &bOK);
53 if( bOK && dwSize == sizeof(OWSharedData) )
54 pRData = (POWSharedData)regReadBinaryData(hk, "OWData");
55 regCloseKey(hk);
58 // Create a file mapping object against the system virtual memory.
59 // This will be used to share data between the application and instances of the dll.
60 ghSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(OWSharedData), OW_SHARED_FILE_MAPPING);
61 if(ghSharedMem)
63 // map a view of the file
64 gPowData = (POWSharedData)MapViewOfFile(ghSharedMem, FILE_MAP_WRITE, 0,0,0);
65 if( gPowData )
67 // clear the shared mem
68 ZeroMemory(gPowData, sizeof(OWSharedData));
69 // if we succeeded in loading saved data, copy it back
70 if( pRData )
71 CopyMemory(gPowData, pRData, sizeof(OWSharedData));
72 else
74 // initialise the memory to useful values.
75 int w,h;
76 w = GetSystemMetrics(SM_CXSCREEN);
77 h = GetSystemMetrics(SM_CYSCREEN);
78 gPowData->ptOrg.x = w/2 - w/4;
79 gPowData->ptOrg.y = (h - 2*h/3)/2;
80 gPowData->szDim.cx = w/2;
81 gPowData->szDim.cy = 2*h/3;
82 gPowData->iView = V_DETAILS;
83 gPowData->iFocus = F_DIRLIST;
84 gPowData->bShowIcon = 1;
86 gPowData->hwListener = hwnd;
87 gPowData->bDisable = 0;
88 gPowData->refCount = 0;
89 giCloseMessage = gPowData->iCloseMsg = RegisterWindowMessage("Lingo.OpenWide.ProcessFinished.Message");
90 rVal = 1;
94 if( pRData )
95 free(pRData);
97 releaseMutex();
98 return rVal;
103 void releaseSharedMem(void)
105 // dbg("DLL: Waiting for mutex");
106 if( ghMutex )
108 DWORD dwRes = WaitForSingleObject(ghMutex, INFINITE);
109 if(dwRes != WAIT_OBJECT_0)
111 // dbg("DLL: Failed to get ownership of mutex in releaseSharedMem!!!");
112 return;
116 // dbg("DLL: Releasing file mapping");
117 if( ghSharedMem )
119 if( gPowData );
121 UnmapViewOfFile(gPowData);
122 gPowData = NULL;
124 CloseHandle(ghSharedMem);
125 ghSharedMem = NULL;
127 ReleaseMutex(ghMutex);
130 int doApply(HWND hwnd)
132 DWORD dwRes;
133 if( ghMutex )
135 dwRes = WaitForSingleObject(ghMutex, INFINITE);
136 switch(dwRes)
138 case WAIT_OBJECT_0:
139 // okay, continue
140 break;
141 case WAIT_ABANDONED:
142 default:
143 return 0;
146 BOOL bOK;
147 int i = GetDlgItemInt(hwnd, IDE_LEFT, &bOK, TRUE);
148 if( bOK )
149 gPowData->ptOrg.x = i;
150 i = GetDlgItemInt(hwnd, IDE_TOP, &bOK, TRUE);
151 if( bOK )
152 gPowData->ptOrg.y = i;
153 i = GetDlgItemInt(hwnd, IDE_WIDTH, &bOK, TRUE);
154 if( bOK )
155 gPowData->szDim.cx = i;
156 i = GetDlgItemInt(hwnd, IDE_HEIGHT, &bOK, TRUE);
157 if( bOK )
158 gPowData->szDim.cy = i;
159 int idx = SendDlgItemMessage(hwnd, IDCB_FOCUS, CB_GETCURSEL, 0, 0);
160 if( idx != CB_ERR )
162 int f = SendDlgItemMessage(hwnd, IDCB_FOCUS, CB_GETITEMDATA, idx, 0);
163 if( f >= 0 && f < F_MAX )
164 gPowData->iFocus = f;
166 idx = SendDlgItemMessage(hwnd, IDCB_VIEW, CB_GETCURSEL, 0, 0);
167 if( idx != CB_ERR )
169 int v = SendDlgItemMessage(hwnd, IDCB_VIEW, CB_GETITEMDATA, idx, 0);
170 if( v >= 0 && v < V_MAX )
171 gPowData->iView = v;
173 gPowData->bStartMin = IsDlgButtonChecked(hwnd, IDC_STARTMIN) == BST_CHECKED;
174 BOOL bWinStart = IsDlgButtonChecked(hwnd, IDC_WSTARTUP) == BST_CHECKED;
176 HKEY hk = regCreateKey(HKEY_CURRENT_USER, OW_REGKEY_NAME);
177 if( hk )
179 regWriteDWORD(hk, NULL, sizeof(OWSharedData));
180 regWriteBinaryData(hk, "OWData", (byte *)gPowData, sizeof(OWSharedData));
181 regCloseKey(hk);
184 if( ghMutex )
185 ReleaseMutex(ghMutex);
187 setStartupApp(hwnd, bWinStart);
188 return 1;
193 BOOL isStartupApp(HWND hwnd)
195 static char szBuf[MAX_PATH+1];
196 HRESULT hRes = SHGetFolderPath(hwnd, CSIDL_STARTUP, NULL, SHGFP_TYPE_CURRENT, szBuf);
197 if( hRes == S_OK )
199 PathAppend(szBuf, "OpenWide.lnk");
200 return fileExists(szBuf);
202 return FALSE;
205 int setStartupApp(HWND hwnd, BOOL bSet)
207 char szBuf[MAX_PATH+1], szModule[MAX_PATH+1];
209 ZeroMemory(szBuf, sizeof(szBuf)/sizeof(char));
210 ZeroMemory(szModule, sizeof(szBuf)/sizeof(char));
212 if( !GetModuleFileName(NULL, szModule, MAX_PATH) )
213 return 0;
214 HRESULT hRes = SHGetFolderPath(hwnd, CSIDL_STARTUP, NULL, SHGFP_TYPE_CURRENT, szBuf);
215 if( hRes != S_OK || !PathAppend(szBuf, "OpenWide.lnk"))
216 return 0;
217 if( bSet )
219 if( fileExists(szBuf) )
220 hRes = delFile(hwnd, szBuf);
221 hRes = CreateLink(szModule, szBuf, "OpenWide - control Open&Save dialogs...");
222 return hRes == S_OK;
224 else
226 return delFile(hwnd, szBuf);
230 int initListener(HWND hwnd)
232 if(!initSharedMem(hwnd))
233 return 0;
235 BOOL bMinimize = FALSE, bIcon = TRUE;
237 // wait for then lock shared data
238 if( !waitForMutex() )
239 return 0;
241 bMinimize = gPowData->bStartMin;
242 bIcon = gPowData->bShowIcon;
244 /// released shared data
245 releaseMutex();
247 if(bIcon)
248 addTrayIcon(hwnd);
250 if( bMinimize )
251 ghwPropSheet = NULL;
252 else
253 ghwPropSheet = showDlg(hwnd);
255 if( !setHook() )
257 Warn( "Failed to set hook: %s", geterrmsg() );
258 return 0;
260 return 1;
263 void doTrayMenu(HWND hwnd)
265 if( ghwPropSheet )
266 SetForegroundWindow(ghwPropSheet);
268 HMENU hm = CreatePopupMenu();
269 AppendMenu(hm, MF_STRING, IDM_ABOUT, "&About OpenWide...");
270 AppendMenu(hm, MF_GRAYED | MF_SEPARATOR, 0, NULL);
271 AppendMenu(hm, MF_STRING | (ghwPropSheet ? MF_GRAYED : 0), IDM_SETTINGS, "&Settings...");
272 AppendMenu(hm, MF_STRING | (ghwPropSheet ? MF_GRAYED : 0), IDM_QUIT, "&Quit");
274 SetMenuDefaultItem(hm, IDM_SETTINGS, FALSE);
276 POINT pt;
277 GetCursorPos(&pt);
278 TrackPopupMenu(hm, TPM_RIGHTBUTTON | TPM_BOTTOMALIGN | TPM_RIGHTALIGN,
279 pt.x, pt.y, 0, hwnd, NULL);
280 DestroyMenu(hm);
283 void showSettingsDlg(HWND hwnd)
285 if( ghwPropSheet )
287 ShowWindow(ghwPropSheet, SW_SHOWNORMAL);
288 SetForegroundWindow(ghwPropSheet);
290 else
291 ghwPropSheet = showDlg(hwnd);
294 void doQuit(void)
296 if( ghwPropSheet )
298 SetForegroundWindow(ghwPropSheet);
299 Warn("Please close the settings dialog box before trying to quit");
300 return;
302 //rmvHook();
303 if( waitForMutex() )
305 // dbg("Setting bDisable");
306 gPowData->bDisable = TRUE;
307 // dbg("refCount is %d", gPowData->refCount);
308 if(gPowData->refCount == 0)
310 // dbg("Posting quit message");
311 PostQuitMessage(0);
313 releaseMutex();
315 remTrayIcon(ghwMain);
318 LRESULT WINAPI CALLBACK wpListener(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
320 static UINT uTaskbarMsg=0;
321 switch(msg)
323 case WM_CREATE:
324 if(!initListener(hwnd))
326 Warn("OpenWide failed to initialize properly. Please report this bug:\r\nErr msg: %s", geterrmsg());
327 return -1;
329 uTaskbarMsg = RegisterWindowMessage("TaskbarCreated");
330 break;
331 case WM_COMMAND:
332 switch(LOWORD(wp))
334 case IDM_ABOUT:
335 MessageBox(hwnd, "OpenWide is written by Luke Hudson. (c)2005\r\nSee http://lingo.atspace.com", "About OpenWide", MB_OK);
336 break;
337 case IDM_SETTINGS:
338 showSettingsDlg(hwnd);
339 break;
340 case IDM_QUIT:
341 doQuit();
342 break;
344 break;
345 case WM_TRAYICON:
346 switch(lp)
348 case WM_RBUTTONDOWN:
349 doTrayMenu(hwnd);
350 break;
351 case WM_LBUTTONDBLCLK:
352 showSettingsDlg(hwnd);
353 break;
354 case WM_LBUTTONUP:
355 /* ShowWindow(hwnd, SW_SHOWNORMAL);
356 EnableWindow(hwnd, TRUE);
357 remTrayIcon(hwnd);
358 SetFocus(hwnd);*/
359 break;
361 break;
362 case WM_DESTROY:
363 // dbg("OWApp: listener destroying");
364 rmvHook();
365 releaseSharedMem();
366 break;
367 default:
368 if( msg == giCloseMessage )
370 // dbg("OWApp: Received dll close msg");
371 if( waitForMutex() )
373 // dbg("OWApp: refCount is %d", gPowData->refCount);
374 if( gPowData->refCount == 0 && gPowData->bDisable)
375 PostQuitMessage(0);
376 releaseMutex();
379 else if( msg == uTaskbarMsg ) // taskbar re-created, re-add icon if option is enabled.
381 if( !waitForMutex() )
382 return 0;
383 BOOL bIcon = gPowData->bShowIcon;
384 releaseMutex();
386 if(bIcon) addTrayIcon(hwnd);
388 return DefWindowProc(hwnd, msg, wp, lp);
390 return 0;
394 BOOL WINAPI CALLBACK wpPlacement(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
396 static LPRECT pr = NULL;
397 static BOOL bXP;
398 switch(msg)
400 case WM_INITDIALOG:
401 pr = (LPRECT)lp;
402 if(!pr)
403 EndDialog(hwnd, 0);
404 bXP = isWinXP();
405 MoveWindow(hwnd, pr->left, pr->top, pr->right, pr->bottom, FALSE);
406 break;
407 case WM_COMMAND:
408 switch(LOWORD(wp))
410 case IDOK:
411 GetWindowRect(hwnd, pr);
412 EndDialog(hwnd, 1);
413 break;
414 case IDCANCEL:
415 EndDialog(hwnd, 0);
416 break;
418 break;
419 case WM_GETMINMAXINFO:
421 MINMAXINFO * pmm = (MINMAXINFO *)lp;
422 if(!pmm)
423 break;
424 if( bXP )
426 pmm->ptMinTrackSize.x = OW_XP_MINWIDTH;
427 pmm->ptMinTrackSize.y = OW_XP_MINHEIGHT;
429 else
431 pmm->ptMinTrackSize.x = OW_2K_MINWIDTH;
432 pmm->ptMinTrackSize.y = OW_2K_MINHEIGHT;
435 break;
436 case WM_CLOSE:
437 EndDialog(hwnd, 0);
438 break;
439 default:
440 return 0;
442 return 1;
445 int addTrayIcon(HWND hwnd)
447 return Add_TrayIcon( ghIconSm, "OpenWide\r\nRight-Click for menu...", hwnd, WM_TRAYICON, 0);
450 void remTrayIcon(HWND hwnd)
452 Rem_TrayIcon( hwnd, WM_TRAYICON, 0 );
455 HWND createListenerWindow(void)
457 static BOOL bRegd = FALSE;
458 if(!bRegd)
460 WNDCLASSEX wc;
461 ZeroMemory(&wc, sizeof(wc));
462 wc.cbSize = sizeof(wc);
463 wc.hInstance = ghInstance;
464 wc.lpfnWndProc = wpListener;
465 wc.lpszClassName = "Lingo.OpenWide.Listener";
466 wc.hIcon = ghIconLG;
467 wc.hIconSm = ghIconSm;
468 bRegd = (RegisterClassEx(&wc) != 0);
470 return CreateWindowEx( WS_EX_NOACTIVATE, "Lingo.OpenWide.Listener", "Lingo.OpenWide",
471 WS_POPUP, 0,0, 1,1, NULL, NULL, ghInstance, NULL);
474 int createWin(void)
476 ghwMain = createListenerWindow();
477 return 1;
480 int ow_init(void)
482 HRESULT hRes = CoInitialize(NULL);
483 if( hRes != S_OK && hRes != S_FALSE )
484 return 0;
485 ghIconSm = (HICON)LoadImage(ghInstance, MAKEINTRESOURCE(IDI_TRAY), IMAGE_ICON, 16,16, LR_SHARED | LR_VGACOLOR);
486 ghIconLG = (HICON)LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_TRAY));
487 if( !createWin() )
488 return 0;
489 return 1;
493 void ow_shutdown(void)
495 if(ghwMain)
497 DestroyWindow(ghwMain);
498 ghwMain = NULL;
500 CoUninitialize();
504 int WINAPI WinMain(HINSTANCE hi, HINSTANCE hiPrv, LPSTR fakeCmdLine, int iShow)
506 HANDLE hMutex = NULL;
507 hMutex = CreateMutex(NULL, FALSE, "OpenWide_App_Mutex");
508 if( hMutex && GetLastError()==ERROR_ALREADY_EXISTS )
510 CloseHandle(hMutex);
511 HWND hw = FindWindowEx(NULL, NULL, "Lingo.OpenWide.Listener", "Lingo.OpenWide");
512 if(hw)
513 SendMessage(hw, WM_TRAYICON, 0, WM_LBUTTONDBLCLK);
514 return 0;
516 ghInstance = hi;
517 if( !ow_init() )
519 ow_shutdown();
520 return 0;
523 MSG msg;
524 int ret;
526 while( (ret = GetMessage(&msg, NULL, 0,0) ) != 0 )
528 if( ret == -1 )
529 break;
530 if( !PropSheet_IsDialogMessage(ghwPropSheet, &msg) ) //IsDialogMessage(ghwMain, &msg) )
532 TranslateMessage(&msg);
533 DispatchMessage(&msg);
535 if( !PropSheet_GetCurrentPageHwnd(ghwPropSheet) )
537 DestroyWindow(ghwPropSheet);
538 ghwPropSheet=NULL;
541 // dbg("OWApp: Shutting down");
542 ow_shutdown();
543 return 0;