xref: /reactos/dll/shellext/deskmon/deskmon.c (revision 8a978a17)
1 #include "precomp.h"
2 
3 #include <tchar.h>
4 
5 #define NDEBUG
6 #include <debug.h>
7 
8 #include "resource.h"
9 
10 static HINSTANCE hInstance;
11 
12 #ifdef UNICODE
13 typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCWSTR,LPCWSTR,BOOL);
14 #define FUNC_DEVICEPROPERTIES "DevicePropertiesW"
15 #else
16 typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCSTR,LPCSTR,BOOL);
17 #define FUNC_DEVICEPROPERTIES "DevicePropertiesA"
18 #endif
19 
20 static LPTSTR
21 GetMonitorDevInstID(LPCTSTR lpDeviceID)
22 {
23     /* FIXME: Implement, allocate returned string with LocalAlloc! */
24     return NULL;
25 }
26 
27 static VOID
28 ShowMonitorProperties(PDESKMONITOR This)
29 {
30     HMODULE hDevMgr;
31     PDEVICEPROPERTIES pDeviceProperties;
32     LPTSTR lpDevInstID;
33 
34     if (This->SelMonitor != NULL)
35     {
36         lpDevInstID = GetMonitorDevInstID(This->SelMonitor->dd.DeviceID);
37         if (lpDevInstID != NULL)
38         {
39             hDevMgr = LoadLibrary(TEXT("devmgr.dll"));
40             if (hDevMgr != NULL)
41             {
42                 pDeviceProperties = (PDEVICEPROPERTIES)GetProcAddress(hDevMgr,
43                                                                       FUNC_DEVICEPROPERTIES);
44                 if (pDeviceProperties != NULL)
45                 {
46                     pDeviceProperties(This->hwndDlg,
47                                        NULL,
48                                        This->SelMonitor->dd.DeviceID,
49                                        FALSE);
50                 }
51 
52                 FreeLibrary(hDevMgr);
53             }
54 
55             LocalFree((HLOCAL)lpDevInstID);
56         }
57     }
58 }
59 
60 static VOID
61 UpdateMonitorSelection(PDESKMONITOR This)
62 {
63     INT i;
64 
65     if (This->dwMonitorCount > 1)
66     {
67         This->SelMonitor = NULL;
68 
69         i = (INT)SendDlgItemMessage(This->hwndDlg,
70                                     IDC_MONITORLIST,
71                                     LB_GETCURSEL,
72                                     0,
73                                     0);
74         if (i >= 0)
75         {
76             This->SelMonitor = (PDESKMONINFO)SendDlgItemMessage(This->hwndDlg,
77                                                                 IDC_MONITORLIST,
78                                                                 LB_GETITEMDATA,
79                                                                 (WPARAM)i,
80                                                                 0);
81         }
82     }
83     else
84         This->SelMonitor = This->Monitors;
85 
86     EnableWindow(GetDlgItem(This->hwndDlg,
87                             IDC_MONITORPROPERTIES),
88                  This->SelMonitor != NULL);
89 }
90 
91 static VOID
92 UpdatePruningControls(PDESKMONITOR This)
93 {
94     EnableWindow(GetDlgItem(This->hwndDlg,
95                             IDC_PRUNINGCHECK),
96                  This->bModesPruned && !This->bKeyIsReadOnly);
97     CheckDlgButton(This->hwndDlg,
98                    IDC_PRUNINGCHECK,
99                    (This->bModesPruned && This->bPruningOn) ? BST_CHECKED : BST_UNCHECKED);
100 }
101 
102 static VOID
103 GetPruningSettings(PDESKMONITOR This)
104 {
105     BOOL bModesPruned = FALSE, bKeyIsReadOnly = FALSE, bPruningOn = FALSE;
106 
107     if (This->DeskExtInterface != NULL)
108     {
109         This->DeskExtInterface->GetPruningMode(This->DeskExtInterface->Context,
110                                                &bModesPruned,
111                                                &bKeyIsReadOnly,
112                                                &bPruningOn);
113     }
114 
115     /* Check the boolean values against zero before assigning it to the bitfields! */
116     This->bModesPruned = (bModesPruned != FALSE);
117     This->bKeyIsReadOnly = (bKeyIsReadOnly != FALSE);
118     This->bPruningOn = (bPruningOn != FALSE);
119 
120     UpdatePruningControls(This);
121 }
122 
123 static VOID
124 UpdateRefreshFrequencyList(PDESKMONITOR This)
125 {
126     PDEVMODEW lpCurrentMode, lpMode;
127     TCHAR szBuffer[64];
128     DWORD dwIndex;
129     INT i;
130     BOOL bHasDef = FALSE;
131     BOOL bAdded = FALSE;
132 
133     /* Fill the refresh rate combo box */
134     SendDlgItemMessage(This->hwndDlg,
135                        IDC_REFRESHRATE,
136                        CB_RESETCONTENT,
137                        0,
138                        0);
139 
140     lpCurrentMode = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
141     dwIndex = 0;
142 
143     do
144     {
145         lpMode = This->DeskExtInterface->EnumAllModes(This->DeskExtInterface->Context,
146                                                       dwIndex++);
147         if (lpMode != NULL &&
148             lpMode->dmBitsPerPel == lpCurrentMode->dmBitsPerPel &&
149             lpMode->dmPelsWidth == lpCurrentMode->dmPelsWidth &&
150             lpMode->dmPelsHeight == lpCurrentMode->dmPelsHeight)
151         {
152             /* We're only interested in refresh rates for the current resolution and color depth */
153 
154             if (lpMode->dmDisplayFrequency <= 1)
155             {
156                 /* Default hardware frequency */
157                 if (bHasDef)
158                     continue;
159 
160                 bHasDef = TRUE;
161 
162                 if (!LoadString(hInstance,
163                                 IDS_USEDEFFRQUENCY,
164                                 szBuffer,
165                                 sizeof(szBuffer) / sizeof(szBuffer[0])))
166                 {
167                     szBuffer[0] = TEXT('\0');
168                 }
169             }
170             else
171             {
172                 TCHAR szFmt[64];
173 
174                 if (!LoadString(hInstance,
175                                 IDS_FREQFMT,
176                                 szFmt,
177                                 sizeof(szFmt) / sizeof(szFmt[0])))
178                 {
179                     szFmt[0] = TEXT('\0');
180                 }
181 
182                 _sntprintf(szBuffer,
183                            sizeof(szBuffer) / sizeof(szBuffer[0]),
184                            szFmt,
185                            lpMode->dmDisplayFrequency);
186             }
187 
188             i = (INT)SendDlgItemMessage(This->hwndDlg,
189                                         IDC_REFRESHRATE,
190                                         CB_ADDSTRING,
191                                         0,
192                                         (LPARAM)szBuffer);
193             if (i >= 0)
194             {
195                 bAdded = TRUE;
196 
197                 SendDlgItemMessage(This->hwndDlg,
198                                    IDC_REFRESHRATE,
199                                    CB_SETITEMDATA,
200                                    (WPARAM)i,
201                                    (LPARAM)lpMode);
202 
203                 if (lpMode->dmDisplayFrequency == lpCurrentMode->dmDisplayFrequency)
204                 {
205                     SendDlgItemMessage(This->hwndDlg,
206                                        IDC_REFRESHRATE,
207                                        CB_SETCURSEL,
208                                        (WPARAM)i,
209                                        0);
210                 }
211             }
212         }
213 
214     } while (lpMode != NULL);
215 
216     EnableWindow(GetDlgItem(This->hwndDlg,
217                             IDS_MONITORSETTINGSGROUP),
218                  bAdded);
219     EnableWindow(GetDlgItem(This->hwndDlg,
220                             IDS_REFRESHRATELABEL),
221                  bAdded);
222     EnableWindow(GetDlgItem(This->hwndDlg,
223                             IDC_REFRESHRATE),
224                  bAdded);
225 
226     GetPruningSettings(This);
227 }
228 
229 static VOID
230 InitMonitorDialog(PDESKMONITOR This)
231 {
232     PDESKMONINFO pmi, pminext, *pmilink;
233     DISPLAY_DEVICE dd;
234     BOOL bRet;
235     INT i;
236     DWORD dwIndex;
237 
238     /* Free all allocated monitors */
239     pmi = This->Monitors;
240     This->Monitors = NULL;
241     while (pmi != NULL)
242     {
243         pminext = pmi->Next;
244         LocalFree((HLOCAL)pmi);
245         pmi = pminext;
246     }
247 
248     This->SelMonitor = NULL;
249     This->dwMonitorCount = 0;
250 
251     if (This->lpDisplayDevice != NULL)
252         LocalFree((HLOCAL)This->lpDisplayDevice);
253 
254     This->lpDisplayDevice = QueryDeskCplString(This->pdtobj,
255                                                RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE));
256 
257     if (This->DeskExtInterface != NULL)
258     {
259         if (This->lpDisplayDevice != NULL)
260         {
261             /* Enumerate all monitors */
262             dwIndex = 0;
263             pmilink = &This->Monitors;
264 
265             do
266             {
267                 dd.cb = sizeof(dd);
268                 bRet = EnumDisplayDevices(This->lpDisplayDevice,
269                                           dwIndex++,
270                                           &dd,
271                                           0);
272                 if (bRet)
273                 {
274                     pmi = LocalAlloc(LMEM_FIXED,
275                                      sizeof(*pmi));
276                     if (pmi != NULL)
277                     {
278                         CopyMemory(&pmi->dd,
279                                    &dd,
280                                    sizeof(dd));
281                         pmi->Next = NULL;
282                         *pmilink = pmi;
283                         pmilink = &pmi->Next;
284 
285                         This->dwMonitorCount++;
286                     }
287                 }
288             } while (bRet);
289         }
290 
291         This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
292     }
293     else
294         This->lpDevModeOnInit = NULL;
295 
296     This->lpSelDevMode = This->lpDevModeOnInit;
297 
298     /* Setup the UI depending on how many monitors are attached */
299     if (This->dwMonitorCount == 0)
300     {
301         LPTSTR lpMonitorName;
302 
303         /* This is a fallback, let's hope that desk.cpl can provide us with a monitor name */
304         lpMonitorName = QueryDeskCplString(This->pdtobj,
305                                            RegisterClipboardFormat(DESK_EXT_MONITORNAME));
306 
307         SetDlgItemText(This->hwndDlg,
308                        IDC_MONITORNAME,
309                        lpMonitorName);
310 
311         if (lpMonitorName != NULL)
312             LocalFree((HLOCAL)lpMonitorName);
313     }
314     else if (This->dwMonitorCount == 1)
315     {
316         This->SelMonitor = This->Monitors;
317         SetDlgItemText(This->hwndDlg,
318                        IDC_MONITORNAME,
319                        This->Monitors->dd.DeviceString);
320     }
321     else
322     {
323         SendDlgItemMessage(This->hwndDlg,
324                            IDC_MONITORLIST,
325                            LB_RESETCONTENT,
326                            0,
327                            0);
328 
329         pmi = This->Monitors;
330         while (pmi != NULL)
331         {
332             i = (INT)SendDlgItemMessage(This->hwndDlg,
333                                         IDC_MONITORLIST,
334                                         LB_ADDSTRING,
335                                         0,
336                                         (LPARAM)pmi->dd.DeviceString);
337             if (i >= 0)
338             {
339                 SendDlgItemMessage(This->hwndDlg,
340                                    IDC_MONITORLIST,
341                                    LB_SETITEMDATA,
342                                    (WPARAM)i,
343                                    (LPARAM)pmi);
344 
345                 if (This->SelMonitor == NULL)
346                 {
347                     SendDlgItemMessage(This->hwndDlg,
348                                        IDC_MONITORLIST,
349                                        LB_SETCURSEL,
350                                        (WPARAM)i,
351                                        0);
352 
353                     This->SelMonitor = pmi;
354                 }
355             }
356 
357             pmi = pmi->Next;
358         }
359     }
360 
361     /* Show/Hide controls */
362     ShowWindow(GetDlgItem(This->hwndDlg,
363                           IDC_MONITORNAME),
364                (This->dwMonitorCount <= 1 ? SW_SHOW : SW_HIDE));
365     ShowWindow(GetDlgItem(This->hwndDlg,
366                           IDC_MONITORLIST),
367                (This->dwMonitorCount > 1 ? SW_SHOW : SW_HIDE));
368 
369     UpdateRefreshFrequencyList(This);
370     UpdateMonitorSelection(This);
371 }
372 
373 static VOID
374 UpdatePruningSelection(PDESKMONITOR This)
375 {
376     BOOL bPruningOn;
377 
378     if (This->DeskExtInterface != NULL && This->bModesPruned && !This->bKeyIsReadOnly)
379     {
380         bPruningOn = IsDlgButtonChecked(This->hwndDlg,
381                                         IDC_PRUNINGCHECK) != BST_UNCHECKED;
382 
383         if (bPruningOn != This->bPruningOn)
384         {
385             /* Tell desk.cpl to turn on/off pruning mode */
386             This->bPruningOn = bPruningOn;
387             This->DeskExtInterface->SetPruningMode(This->DeskExtInterface->Context,
388                                                    bPruningOn);
389 
390             /* Fill the refresh rate combobox again, we now receive a filtered
391                or unfiltered device mode list from desk.cpl (depending on whether
392                pruning is active or not) */
393             UpdateRefreshFrequencyList(This);
394 
395             (void)PropSheet_Changed(GetParent(This->hwndDlg),
396                                     This->hwndDlg);
397         }
398     }
399 }
400 
401 static VOID
402 UpdateRefreshRateSelection(PDESKMONITOR This)
403 {
404     PDEVMODEW lpCurrentDevMode;
405     INT i;
406 
407     if (This->DeskExtInterface != NULL)
408     {
409         i = (INT)SendDlgItemMessage(This->hwndDlg,
410                                     IDC_REFRESHRATE,
411                                     CB_GETCURSEL,
412                                     0,
413                                     0);
414         if (i >= 0)
415         {
416             lpCurrentDevMode = This->lpSelDevMode;
417             This->lpSelDevMode = (PDEVMODEW)SendDlgItemMessage(This->hwndDlg,
418                                                                IDC_REFRESHRATE,
419                                                                CB_GETITEMDATA,
420                                                                (WPARAM)i,
421                                                                0);
422 
423             if (This->lpSelDevMode != NULL && This->lpSelDevMode != lpCurrentDevMode)
424             {
425                 This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
426                                                        This->lpSelDevMode);
427 
428                 UpdateRefreshFrequencyList(This);
429 
430                 (void)PropSheet_Changed(GetParent(This->hwndDlg),
431                                         This->hwndDlg);
432             }
433         }
434     }
435 }
436 
437 static LONG
438 ApplyMonitorChanges(PDESKMONITOR This)
439 {
440     LONG lChangeRet;
441 
442     if (This->DeskExtInterface != NULL)
443     {
444         /* Change the display settings through desk.cpl */
445         lChangeRet = DeskCplExtDisplaySaveSettings(This->DeskExtInterface,
446                                                    This->hwndDlg);
447         if (lChangeRet == DISP_CHANGE_SUCCESSFUL)
448         {
449             /* Save the new mode */
450             This->lpDevModeOnInit = This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
451             This->lpSelDevMode = This->lpDevModeOnInit;
452             return PSNRET_NOERROR;
453         }
454         else if (lChangeRet == DISP_CHANGE_RESTART)
455         {
456             /* Notify desk.cpl that the user needs to reboot */
457             PropSheet_RestartWindows(GetParent(This->hwndDlg));
458             return PSNRET_NOERROR;
459         }
460     }
461 
462     InitMonitorDialog(This);
463 
464     return PSNRET_INVALID_NOCHANGEPAGE;
465 }
466 
467 static VOID
468 ResetMonitorChanges(PDESKMONITOR This)
469 {
470     if (This->DeskExtInterface != NULL && This->lpDevModeOnInit != NULL)
471     {
472         This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
473                                                This->lpDevModeOnInit);
474     }
475 }
476 
477 static INT_PTR CALLBACK
478 MonitorDlgProc(HWND hwndDlg,
479                UINT uMsg,
480                WPARAM wParam,
481                LPARAM lParam)
482 {
483     PDESKMONITOR This;
484     INT_PTR Ret = 0;
485 
486     if (uMsg != WM_INITDIALOG)
487     {
488         This = (PDESKMONITOR)GetWindowLongPtr(hwndDlg, DWLP_USER);
489     }
490 
491     switch (uMsg)
492     {
493         case WM_INITDIALOG:
494             This = (PDESKMONITOR)((LPCPROPSHEETPAGE)lParam)->lParam;
495             This->hwndDlg = hwndDlg;
496             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This);
497 
498             InitMonitorDialog(This);
499             Ret = TRUE;
500             break;
501 
502         case WM_COMMAND:
503             switch (LOWORD(wParam))
504             {
505                 case IDC_MONITORPROPERTIES:
506                     ShowMonitorProperties(This);
507                     break;
508 
509                 case IDC_MONITORLIST:
510                     if (HIWORD(wParam) == LBN_SELCHANGE)
511                         UpdateMonitorSelection(This);
512                     break;
513 
514                 case IDC_PRUNINGCHECK:
515                     if (HIWORD(wParam) == BN_CLICKED)
516                         UpdatePruningSelection(This);
517                     break;
518 
519                 case IDC_REFRESHRATE:
520                     if (HIWORD(wParam) == CBN_SELCHANGE)
521                         UpdateRefreshRateSelection(This);
522                     break;
523             }
524             break;
525 
526         case WM_NOTIFY:
527         {
528             NMHDR *nmh = (NMHDR *)lParam;
529 
530             switch (nmh->code)
531             {
532                 case PSN_APPLY:
533                 {
534                     SetWindowLongPtr(hwndDlg,
535                                      DWLP_MSGRESULT,
536                                      ApplyMonitorChanges(This));
537                     break;
538                 }
539 
540                 case PSN_RESET:
541                     ResetMonitorChanges(This);
542                     break;
543 
544                 case PSN_SETACTIVE:
545                     UpdateRefreshFrequencyList(This);
546                     break;
547             }
548             break;
549         }
550     }
551 
552     return Ret;
553 }
554 
555 static VOID
556 IDeskMonitor_Destroy(PDESKMONITOR This)
557 {
558     PDESKMONINFO pmi, pminext;
559 
560     if (This->pdtobj != NULL)
561     {
562         IDataObject_Release(This->pdtobj);
563         This->pdtobj = NULL;
564     }
565 
566     if (This->DeskExtInterface != NULL)
567     {
568         LocalFree((HLOCAL)This->DeskExtInterface);
569         This->DeskExtInterface = NULL;
570     }
571 
572     if (This->lpDisplayDevice != NULL)
573     {
574         LocalFree((HLOCAL)This->lpDisplayDevice);
575         This->lpDisplayDevice = NULL;
576     }
577 
578     /* Free all monitors */
579     pmi = This->Monitors;
580     This->Monitors = NULL;
581     while (pmi != NULL)
582     {
583         pminext = pmi->Next;
584         LocalFree((HLOCAL)pmi);
585         pmi = pminext;
586     }
587 }
588 
589 ULONG
590 IDeskMonitor_AddRef(PDESKMONITOR This)
591 {
592     ULONG ret;
593 
594     ret = InterlockedIncrement((PLONG)&This->ref);
595     if (ret == 1)
596         InterlockedIncrement(&dll_refs);
597 
598     return ret;
599 }
600 
601 ULONG
602 IDeskMonitor_Release(PDESKMONITOR This)
603 {
604     ULONG ret;
605 
606     ret = InterlockedDecrement((PLONG)&This->ref);
607     if (ret == 0)
608     {
609         IDeskMonitor_Destroy(This);
610         InterlockedDecrement(&dll_refs);
611 
612         HeapFree(GetProcessHeap(),
613                  0,
614                  This);
615     }
616 
617     return ret;
618 }
619 
620 HRESULT STDMETHODCALLTYPE
621 IDeskMonitor_QueryInterface(PDESKMONITOR This,
622                             REFIID iid,
623                             PVOID *pvObject)
624 {
625     *pvObject = NULL;
626 
627     if (IsEqualIID(iid,
628                    &IID_IShellPropSheetExt) ||
629         IsEqualIID(iid,
630                    &IID_IUnknown))
631     {
632         *pvObject = impl_to_interface(This, IShellPropSheetExt);
633     }
634     else if (IsEqualIID(iid,
635                         &IID_IShellExtInit))
636     {
637         *pvObject = impl_to_interface(This, IShellExtInit);
638     }
639     else if (IsEqualIID(iid,
640                         &IID_IClassFactory))
641     {
642         *pvObject = impl_to_interface(This, IClassFactory);
643     }
644     else
645     {
646         DPRINT1("IDeskMonitor::QueryInterface(%p,%p): E_NOINTERFACE\n", iid, pvObject);
647         return E_NOINTERFACE;
648     }
649 
650     IDeskMonitor_AddRef(This);
651     return S_OK;
652 }
653 
654 HRESULT
655 IDeskMonitor_Initialize(PDESKMONITOR This,
656                         LPCITEMIDLIST pidlFolder,
657                         IDataObject *pdtobj,
658                         HKEY hkeyProgID)
659 {
660     DPRINT1("IDeskMonitor::Initialize(%p,%p,%p)\n", pidlFolder, pdtobj, hkeyProgID);
661 
662     if (pdtobj != NULL)
663     {
664         IDataObject_AddRef(pdtobj);
665         This->pdtobj = pdtobj;
666 
667         /* Get a copy of the desk.cpl extension interface */
668         This->DeskExtInterface = QueryDeskCplExtInterface(This->pdtobj);
669         if (This->DeskExtInterface != NULL)
670             return S_OK;
671     }
672 
673     return S_FALSE;
674 }
675 
676 HRESULT
677 IDeskMonitor_AddPages(PDESKMONITOR This,
678                       LPFNADDPROPSHEETPAGE pfnAddPage,
679                       LPARAM lParam)
680 {
681     HPROPSHEETPAGE hpsp;
682     PROPSHEETPAGE psp;
683 
684     DPRINT1("IDeskMonitor::AddPages(%p,%p)\n", pfnAddPage, lParam);
685 
686     psp.dwSize = sizeof(psp);
687     psp.dwFlags = PSP_DEFAULT;
688     psp.hInstance = hInstance;
689     psp.pszTemplate = MAKEINTRESOURCE(IDD_MONITOR);
690     psp.pfnDlgProc = MonitorDlgProc;
691     psp.lParam = (LPARAM)This;
692 
693     hpsp = CreatePropertySheetPage(&psp);
694     if (hpsp != NULL && pfnAddPage(hpsp, lParam))
695         return S_OK;
696 
697     return S_FALSE;
698 }
699 
700 HRESULT
701 IDeskMonitor_ReplacePage(PDESKMONITOR This,
702                          EXPPS uPageID,
703                          LPFNADDPROPSHEETPAGE pfnReplacePage,
704                          LPARAM lParam)
705 {
706     DPRINT1("IDeskMonitor::ReplacePage(%u,%p,%p)\n", uPageID, pfnReplacePage, lParam);
707     return E_NOTIMPL;
708 }
709 
710 HRESULT
711 IDeskMonitor_Constructor(REFIID riid,
712                          LPVOID *ppv)
713 {
714     PDESKMONITOR This;
715     HRESULT hRet = E_OUTOFMEMORY;
716 
717     DPRINT1("IDeskMonitor::Constructor(%p,%p)\n", riid, ppv);
718 
719     This = HeapAlloc(GetProcessHeap(),
720                      0,
721                      sizeof(*This));
722     if (This != NULL)
723     {
724         ZeroMemory(This,
725                    sizeof(*This));
726 
727         IDeskMonitor_InitIface(This);
728 
729         hRet = IDeskMonitor_QueryInterface(This,
730                                            riid,
731                                            ppv);
732         if (!SUCCEEDED(hRet))
733             IDeskMonitor_Release(This);
734     }
735 
736     return hRet;
737 }
738 
739 BOOL WINAPI
740 DllMain(HINSTANCE hinstDLL,
741         DWORD dwReason,
742         LPVOID lpvReserved)
743 {
744     switch (dwReason)
745     {
746         case DLL_PROCESS_ATTACH:
747             hInstance = hinstDLL;
748             DisableThreadLibraryCalls(hInstance);
749             break;
750     }
751 
752     return TRUE;
753 }
754