Michael Bruestle (michael_bruestle@yahoo.com)
[reactos.git] / reactos / lib / sdk / scrnsave / scrnsave.c
index 87618ba..8538145 100644 (file)
 /*
-  Screen saver library by Anders Norlander <anorland@hem2.passagen.se>
-
-  This library is (hopefully) compatible with Microsoft's
-  screen saver library.
-
-  This is public domain software.
-
+ * PROJECT:         ReactOS Screen Saver Library
+ * LICENSE:         GPL v2 or any later version
+ * FILE:            lib/sdk/scrnsave/scrnsave.c
+ * PURPOSE:         Library for writing screen savers, compatible with MS' scrnsave.lib
+ * PROGRAMMERS:     Anders Norlander <anorland@hem2.passagen.se>
+ *                  Colin Finck <mail@colinfinck.de>
  */
+
 #include <windows.h>
+#include <tchar.h>
 #include <scrnsave.h>
-#include <regstr.h>
 
-/* screen saver window class */
+// Screen Saver window class
 #define CLASS_SCRNSAVE TEXT("WindowsScreenSaverClass")
 
-/* globals */
-HWND           hMainWindow = NULL;
-BOOL           fChildPreview = FALSE;
-HINSTANCE      hMainInstance;
-TCHAR          szName[TITLEBARNAMELEN];
-TCHAR          szAppName[APPNAMEBUFFERLEN];
-TCHAR          szIniFile[MAXFILELEN];
-TCHAR          szScreenSaver[22];
-TCHAR          szHelpFile[MAXFILELEN];
-TCHAR          szNoHelpMemory[BUFFLEN];
-UINT           MyHelpMessage;
-
-/* local house keeping */
-static HINSTANCE hPwdLib = NULL;
+// Globals
+HWND        hMainWindow = NULL;
+BOOL        fChildPreview = FALSE;
+HINSTANCE   hMainInstance;
+TCHAR       szName[TITLEBARNAMELEN];
+TCHAR       szAppName[APPNAMEBUFFERLEN];
+TCHAR       szIniFile[MAXFILELEN];
+TCHAR       szScreenSaver[22];
+TCHAR       szHelpFile[MAXFILELEN];
+TCHAR       szNoHelpMemory[BUFFLEN];
+UINT        MyHelpMessage;
+
+// Local house keeping
 static POINT pt_orig;
-static BOOL checking_pwd = FALSE;
-static BOOL closing = FALSE;
-static BOOL w95 = FALSE;
-
-typedef BOOL (WINAPI *VERIFYPWDPROC)(HWND);
-typedef DWORD (WINAPI *CHPWDPROC)(LPCTSTR, HWND, DWORD, PVOID);
-static VERIFYPWDPROC VerifyScreenSavePwd = NULL;
-
-/* function names */
-#define szVerifyPassword "VerifyScreenSavePwd"
-
-#ifdef UNICODE
-#define szPwdChangePassword "PwdChangePasswordW"
-#else
-#define szPwdChangePassword "PwdChangePasswordA"
-#endif
-
-static void TerminateScreenSaver(HWND hWnd);
-static BOOL RegisterClasses(void);
-static LRESULT WINAPI SysScreenSaverProc(HWND,UINT,WPARAM,LPARAM);
-static int LaunchScreenSaver(HWND hParent);
-static void LaunchConfig(void);
-
-static int ISSPACE(char c)
+
+static int ISSPACE(TCHAR c)
 {
-  return (c == ' ' || c == '\t');
+    return (c == ' ' || c == '\t');
 }
 
 #define ISNUM(c) ((c) >= '0' && c <= '9')
-static unsigned long
-_toul(const char *s)
+
+static ULONG_PTR _toulptr(const TCHAR *s)
 {
-  unsigned long res;
-  unsigned long n;
-  const char *p;
-  for (p = s; *p; p++)
-    if (!ISNUM(*p)) break;
-  p--;
-  res = 0;
-  for (n = 1; p >= s; p--, n *= 10)
-    res += (*p - '0') * n;
-  return res;
+    ULONG_PTR res;
+    ULONG_PTR n;
+    const TCHAR *p;
+
+    for (p = s; *p; p++)
+        if (!ISNUM(*p))
+            break;
+
+    p--;
+    res = 0;
+
+    for (n = 1; p >= s; p--, n *= 10)
+        res += (*p - '0') * n;
+
+    return res;
 }
 
-/* screen saver entry point */
-int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
-                     LPSTR CmdLine, int nCmdShow)
+// This function takes care of *must* do tasks, like terminating screen saver
+static LRESULT WINAPI SysScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-  LPSTR p;
-  OSVERSIONINFO vi;
+    switch(uMsg)
+    {
+        case WM_CREATE:
+            // Mouse is not supposed to move from this position
+            GetCursorPos(&pt_orig);
+            break;
 
-  /* initialize */
-  hMainInstance = hInst;
+        case WM_DESTROY:
+            PostQuitMessage(0);
+            break;
 
-  vi.dwOSVersionInfoSize = sizeof(vi);
-  GetVersionEx(&vi);
-  /* check if we are going to check for passwords */
-  if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
-    {
-      HKEY hKey;
-      /* we are using windows 95 */
-      w95 = TRUE;
-      if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE ,&hKey) ==
-          ERROR_SUCCESS)
-        {
-          DWORD check_pwd;
-          DWORD size = sizeof(DWORD);
-          DWORD type;
-          LONG res;
-          res = RegQueryValueEx(hKey, REGSTR_VALUE_USESCRPASSWORD,
-                                NULL, &type, (PBYTE) &check_pwd, &size);
-          if (check_pwd && res == ERROR_SUCCESS)
+        case WM_SYSCOMMAND:
+            if (!fChildPreview)
             {
-              hPwdLib = LoadLibrary(TEXT("PASSWORD.CPL"));
-              if (hPwdLib)
-                VerifyScreenSavePwd = GetProcAddress(hPwdLib, szVerifyPassword);
+                switch (wParam)
+                {
+                    case SC_CLOSE:
+                    case SC_SCREENSAVE:
+                        return FALSE;
+                }
             }
-          RegCloseKey(hKey);
-        }
+            break;
     }
 
-  /* parse arguments */
-  for (p = CmdLine; *p; p++)
+    return ScreenSaverProc(hWnd, uMsg, wParam, lParam);
+}
+
+LRESULT WINAPI DefScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    // Don't do any special processing when in preview mode
+    if (fChildPreview)
+        return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+    switch (uMsg)
     {
-      switch (*p)
+        case WM_NCACTIVATE:
+        case WM_ACTIVATE:
+        case WM_ACTIVATEAPP:
+            if (!wParam)
+            {
+                // wParam is FALSE, so the screensaver is losing the focus.
+                PostMessage(hWnd, WM_CLOSE, 0, 0);
+            }
+            break;
+
+        case WM_MOUSEMOVE:
         {
-        case 'S':
-        case 's':
-          /* start screen saver */
-          return LaunchScreenSaver(NULL);
-          
-        case 'P':
-        case 'p':
-          {
-            /* start screen saver in preview window */
-            HWND hParent;
-            fChildPreview = TRUE;
-            while (ISSPACE(*++p));
-            hParent = (HWND) _toul(p);
-            if (hParent && IsWindow(hParent))
-              return LaunchScreenSaver(hParent);
-          }
-          return 0;
-
-        case 'C':
-        case 'c':
-          /* display configure dialog */
-          LaunchConfig();
-          return 0;
-
-        case 'A':
-        case 'a':
-          {
-            /* change screen saver password */
-            HWND hParent;
-            while (ISSPACE(*++p));
-            hParent = (HWND) _toul(p);
-            if (!hParent || !IsWindow(hParent))
-              hParent = GetForegroundWindow();
-            ScreenSaverChangePassword(hParent);
-          }
-          return 0;
-
-        case '-':
-        case '/':
-        case ' ':
-        default: 
-         break;
+            POINT pt;
+            GetCursorPos(&pt);
+            if (pt.x == pt_orig.x && pt.y == pt_orig.y)
+                break;
+
+            // Fall through
         }
+
+        case WM_LBUTTONDOWN:
+        case WM_RBUTTONDOWN:
+        case WM_MBUTTONDOWN:
+        case WM_KEYDOWN:
+        case WM_KEYUP:
+            // Send a WM_CLOSE to close the screen saver (allows the screensaver author to do clean-up tasks)
+            PostMessage(hWnd, WM_CLOSE, 0, 0);
+            break;
+
+        case WM_SETCURSOR:
+            SetCursor(NULL);
+            return TRUE;
     }
-  LaunchConfig();
-  return 0;
+
+    return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 
-static void LaunchConfig(void)
+// Registers the screen saver window class
+static BOOL RegisterScreenSaverClass(void)
 {
-  /* FIXME: should this be called */
-  RegisterDialogClasses(hMainInstance);
-  /* display configure dialog */
-  DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE),
-            GetForegroundWindow(), (DLGPROC) ScreenSaverConfigureDialog);
+    WNDCLASS cls = {0,};
+
+    cls.hIcon = LoadIcon(hMainInstance, MAKEINTATOM(ID_APP));
+    cls.lpszClassName = CLASS_SCRNSAVE;
+    cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+    cls.hInstance = hMainInstance;
+    cls.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_PARENTDC;
+    cls.lpfnWndProc = (WNDPROC)SysScreenSaverProc;
+
+    return RegisterClass(&cls) != 0;
 }
 
+static void LaunchConfig(void)
+{
+    // Only show the dialog if the RegisterDialogClasses function succeeded.
+    // This is the same behaviour as MS' scrnsave.lib.
+    if( RegisterDialogClasses(hMainInstance) )
+        DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE), GetForegroundWindow(), (DLGPROC) ScreenSaverConfigureDialog);
+}
 
 static int LaunchScreenSaver(HWND hParent)
 {
-  BOOL foo;
-  UINT style;
-  RECT rc;
-  MSG msg;
-
-  /* don't allow other tasks to get into the foreground */
-  if (w95 && !fChildPreview)
-    SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, &foo, 0);
-
-  msg.wParam = 0;
+    UINT style;
+    RECT rc;
+    MSG msg;
 
-  /* register classes, both user defined and classes used by screen saver
-     library */
-  if (!RegisterClasses())
+    if (!RegisterScreenSaverClass())
     {
-      MessageBox(NULL, TEXT("RegisterClasses() failed"), NULL, MB_ICONHAND);
-      goto restore;
+        MessageBox(NULL, TEXT("RegisterClass() failed"), NULL, MB_ICONHAND);
+        return 1;
     }
 
-  /* a slightly different approach needs to be used when displaying
-     in a preview window */
-  if (hParent)
+    // A slightly different approach needs to be used when displaying in a preview window
+    if (hParent)
     {
-      style = WS_CHILD;
-      GetClientRect(hParent, &rc);
+        style = WS_CHILD;
+        GetClientRect(hParent, &rc);
     }
-  else
+    else
     {
-      style = WS_POPUP;
-      rc.right = GetSystemMetrics(SM_CXSCREEN);
-      rc.bottom = GetSystemMetrics(SM_CYSCREEN);
-      style |= WS_VISIBLE;
+        style = WS_POPUP;
+        rc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+        rc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+        style |= WS_VISIBLE;
     }
 
-  /* create main screen saver window */
-  hMainWindow = CreateWindowEx(hParent ? 0 : WS_EX_TOPMOST, CLASS_SCRNSAVE,
-                               TEXT("SCREENSAVER"), style,
-                               0, 0, rc.right, rc.bottom, hParent, NULL,
-                               hMainInstance, NULL);
+    // Create the main screen saver window
+    hMainWindow = CreateWindowEx(hParent ? 0 : WS_EX_TOPMOST, CLASS_SCRNSAVE,
+                                 TEXT("SCREENSAVER"), style,
+                                 0, 0, rc.right, rc.bottom, hParent, NULL,
+                                 hMainInstance, NULL);
 
-  /* display window and start pumping messages */
-  if (hMainWindow)
-    {
-      UpdateWindow(hMainWindow);
-      ShowWindow(hMainWindow, SW_SHOW);
+    if(!hMainWindow)
+        return 1;
 
-      while (GetMessage(&msg, NULL, 0, 0) == TRUE)
-        {
-          TranslateMessage(&msg);
-          DispatchMessage(&msg);
-        }
-    }
+    // Display window and start pumping messages
+    ShowWindow(hMainWindow, SW_SHOW);
+    if (!hParent)
+        SetCursor(NULL);
 
-restore:
-  /* restore system */
-  if (w95 && !fChildPreview)
-    SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, &foo, 0);
-  FreeLibrary(hPwdLib);
-  return msg.wParam;
-}
+    while (GetMessage(&msg, NULL, 0, 0))
+        DispatchMessage(&msg);
 
-/* this function takes care of *must* do tasks, like terminating
-   screen saver */
-static LRESULT WINAPI SysScreenSaverProc(HWND hWnd, UINT msg,
-                                  WPARAM wParam, LPARAM lParam)
-{
-  switch (msg)
-    {
-    case WM_CREATE:
-      if (!fChildPreview)
-        SetCursor(NULL);
-      /* mouse is not supposed to move from this position */
-      GetCursorPos(&pt_orig);
-      break;
-    case WM_DESTROY:
-      PostQuitMessage(0);
-      break;
-    case WM_TIMER:
-      if (closing)
-        return 0;
-      break;
-    case WM_PAINT:
-      if (closing)
-        return DefWindowProc(hWnd, msg, wParam, lParam);
-      break;
-    case WM_SYSCOMMAND:
-      if (!fChildPreview)
-        switch (wParam)
-          {
-          case SC_CLOSE:
-          case SC_SCREENSAVE:
-          case SC_NEXTWINDOW:
-          case SC_PREVWINDOW:
-            return FALSE;
-          }
-      break;
-    case WM_MOUSEMOVE:
-    case WM_LBUTTONDOWN:
-    case WM_RBUTTONDOWN:
-    case WM_MBUTTONDOWN:
-    case WM_KEYDOWN:
-    case WM_SYSKEYDOWN:
-    case WM_NCACTIVATE:
-    case WM_ACTIVATE:
-    case WM_ACTIVATEAPP:
-      if (closing)
-        return DefWindowProc(hWnd, msg, wParam, lParam);
-      break;
-    }
-  return ScreenSaverProc(hWnd, msg, wParam, lParam);
+    return msg.wParam;
 }
 
-LONG WINAPI DefScreenSaverProc(HWND hWnd, UINT msg,
-                               WPARAM wParam, LPARAM lParam)
+// Screen Saver entry point
+int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR CmdLine, int nCmdShow)
 {
-  /* don't do any special processing when in preview mode */
-  if (fChildPreview || closing)
-    return DefWindowProc(hWnd, msg, wParam, lParam);
+    LPTSTR p;
 
-  switch (msg)
-    {
-    case WM_CLOSE:
-      TerminateScreenSaver(hWnd);
-      /* do NOT pass this to DefWindowProc; it will terminate even if
-         an invalid password was given.
-       */
-      return 0;
-    case SCRM_VERIFYPW: 
-      /* verify password or return TRUE if password checking is turned off */
-      if (VerifyScreenSavePwd) 
-        return VerifyScreenSavePwd(hWnd);
-      else
-        return TRUE;
-    case WM_SETCURSOR:
-      if (checking_pwd)
-        break;
-      SetCursor(NULL);
-      return TRUE;
-    case WM_NCACTIVATE:
-    case WM_ACTIVATE:
-    case WM_ACTIVATEAPP:
-      if (wParam != FALSE)
-        break;
-    case WM_MOUSEMOVE:
-      {
-        POINT pt;
-        GetCursorPos(&pt);
-        if (pt.x == pt_orig.x && pt.y == pt_orig.y)
-          break;
-      }
-    case WM_LBUTTONDOWN:
-    case WM_RBUTTONDOWN:
-    case WM_MBUTTONDOWN:
-    case WM_KEYDOWN:
-    case WM_SYSKEYDOWN:
-      /* try to terminate screen saver */
-      if (!checking_pwd)
-        PostMessage(hWnd, WM_CLOSE, 0, 0);
-      break;
-    }
-  return DefWindowProc(hWnd, msg, wParam, lParam);
-}
+       UNREFERENCED_PARAMETER(nCmdShow);
+       UNREFERENCED_PARAMETER(hPrevInst);
 
-static void TerminateScreenSaver(HWND hWnd)
-{
-  /* don't allow recursion */
-  if (checking_pwd || closing)
-    return;
+    hMainInstance = hInst;
 
-  /* verify password */
-  if (VerifyScreenSavePwd)
+    // Parse the arguments
+    for (p = CmdLine; *p; p++)
     {
-      checking_pwd = TRUE;
-      closing = SendMessage(hWnd, SCRM_VERIFYPW, 0, 0);
-      checking_pwd = FALSE;
-    }
-  else
-    closing = TRUE;
+        switch (*p)
+        {
+            case 'S':
+            case 's':
+                // Start the screen saver
+                return LaunchScreenSaver(NULL);
 
-  /* are we closing? */
-  if (closing)
-    {
-      DestroyWindow(hWnd);
-    }
-  else
-    GetCursorPos(&pt_orig); /* if not: get new mouse position */
-}
+            case 'P':
+            case 'p':
+            {
+                // Start the screen saver in preview mode
+                HWND hParent;
+                fChildPreview = TRUE;
 
-/*
-  Register screen saver window class and call user
-  supplied hook.
- */
-static BOOL RegisterClasses(void)
-{
-  WNDCLASS cls;
-  ZeroMemory(&cls, sizeof(cls));
-  cls.hCursor = NULL; 
-  cls.hIcon = LoadIcon(hMainInstance, MAKEINTATOM(ID_APP)); 
-  cls.lpszMenuName = NULL;
-  cls.lpszClassName = CLASS_SCRNSAVE;
-  cls.hbrBackground = NULL; //(HBRUSH)GetStockObject(BLACK_BRUSH);
-  cls.hInstance = hMainInstance;
-  cls.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_PARENTDC;
-  cls.lpfnWndProc = (WNDPROC) SysScreenSaverProc;
-  cls.cbWndExtra = 0;
-  cls.cbClsExtra = 0;
-  
-  if (!RegisterClass(&cls))
-    return FALSE;
-
-  return RegisterDialogClasses(hMainInstance);
-}
+                while (ISSPACE(*++p));
+                hParent = (HWND) _toulptr(p);
 
-void WINAPI ScreenSaverChangePassword(HWND hParent)
-{
-  /* load Master Password Router (MPR) */
-  HINSTANCE hMpr = LoadLibrary(TEXT("MPR.DLL"));
-  
-  if (hMpr)
-    {
-      CHPWDPROC ChangePassword;
-      ChangePassword = (CHPWDPROC) GetProcAddress(hMpr, szPwdChangePassword);
+                if (hParent && IsWindow(hParent))
+                    return LaunchScreenSaver(hParent);
+            }
+            return 0;
+
+            case 'C':
+            case 'c':
+                // Display the configuration dialog
+                LaunchConfig();
+                return 0;
+
+            case '-':
+            case '/':
+            case ' ':
+            default:
+                break;
+        }
+    }
 
-      /* change password for screen saver provider */
-      if (ChangePassword)
-        ChangePassword(TEXT("SCRSAVE"), hParent, 0, NULL);
+    LaunchConfig();
 
-      FreeLibrary(hMpr);
-    }
+    return 0;
 }
-