Correct dependency syntax and autoconf
[shibboleth/cpp-sp.git] / isapi_shib_gui / Shib_PropSheet.cpp
1 #include <windows.h>
2 #include "Shib_PropSheet.h"
3 #include <crtdbg.h>
4 #include <string>
5 #include <tchar.h>
6 #include <strsafe.h>
7 #include "resource.h"
8 #include "globals.h"
9 #include "atou.h"
10 using namespace std;
11
12         
13 void Shib_PropSheet::ReplaceSlashes(string& buf)
14 {
15         size_t p=0;
16
17         while ((p = buf.find('/',p)) != string::npos) {
18                 buf.at(p) = '\\';
19                 p++;
20         }
21 }
22
23 Shib_PropSheet::Shib_PropSheet() : m_cref(0)
24 {
25         for (int i=0;i<NUM_DIRECTIVES;i++) {
26                 directive[i].Init_Directive(i);
27         }
28
29         pwzService=NULL;
30         pwzParentPath=NULL;
31         pwzNode=NULL;
32         pwzMetaPath=NULL;
33         pwzMachineName=NULL;
34         pwzInstance=NULL;
35         pwzRegPath=NULL;
36         OBJECT_CREATED
37 }
38
39
40 Shib_PropSheet::~Shib_PropSheet()
41 {
42         if ( pwzService )
43                 ::LocalFree(pwzService); 
44         if ( pwzParentPath )
45                 ::LocalFree(pwzParentPath);
46         if ( pwzNode )
47                 ::LocalFree(pwzNode);
48         if ( pwzMetaPath )
49                 ::LocalFree(pwzMetaPath);
50         if ( pwzMachineName )
51                 ::LocalFree(pwzMachineName);
52         if ( pwzInstance )
53                 ::LocalFree(pwzInstance);
54         if ( pwzRegPath )
55                 ::LocalFree(pwzRegPath);
56         
57         OBJECT_DESTROYED
58 }
59
60 ///////////////////////
61 // IUnknown implementation
62 ///////////////////////
63
64 STDMETHODIMP Shib_PropSheet::QueryInterface(REFIID riid, LPVOID *ppv)
65 {
66         if (!ppv)
67                 return E_FAIL;
68         
69         *ppv = NULL;
70         
71         if (IsEqualIID(riid, IID_IUnknown))
72                 *ppv = static_cast<IExtendPropertySheet *>(this);
73         else if (IsEqualIID(riid, IID_IExtendPropertySheet))
74                 *ppv = static_cast<IExtendPropertySheet *>(this);
75         
76         if (*ppv) 
77         {
78                 reinterpret_cast<IUnknown *>(*ppv)->AddRef();
79                 return S_OK;
80         }
81         
82         return E_NOINTERFACE;
83 }
84
85 STDMETHODIMP_(ULONG) Shib_PropSheet::AddRef()
86 {
87         return InterlockedIncrement((LONG *)&m_cref);
88 }
89
90 STDMETHODIMP_(ULONG) Shib_PropSheet::Release()
91 {
92         if (InterlockedDecrement((LONG *)&m_cref) == 0)
93         {
94                 // we need to decrement our object count in the DLL
95                 delete this;
96                 return 0;
97         }
98         
99         return m_cref;
100 }
101
102 HRESULT Shib_PropSheet::ExtractData( IDataObject* piDataObject,
103                                                                         CLIPFORMAT   cfClipFormat,
104                                                                         BYTE*        pbData,
105                                                                         DWORD        cbData )
106 {
107         HRESULT hr = S_OK;
108         
109         FORMATETC formatetc = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
110         STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL};
111         
112         stgmedium.hGlobal = ::GlobalAlloc(GPTR, cbData);
113         do 
114         {
115                 if (NULL == stgmedium.hGlobal)
116                 {
117                         hr = E_OUTOFMEMORY;
118                         break;
119                 }
120                 hr = piDataObject->GetDataHere( &formatetc, &stgmedium );
121                 if ( FAILED(hr) )
122                 {
123                         break;
124                 }
125                 
126                 BYTE* pbNewData = reinterpret_cast<BYTE*>(stgmedium.hGlobal);
127                 if (NULL == pbNewData)
128                 {
129                         hr = E_UNEXPECTED;
130                         break;
131                 }
132                 ::memcpy( pbData, pbNewData, cbData );
133         } while (FALSE); 
134         
135         if (NULL != stgmedium.hGlobal)
136         {
137                 ::GlobalFree(stgmedium.hGlobal);
138         }
139         return hr;
140
141
142
143 void Shib_PropSheet::PopulateComboBox()
144 {
145         
146         for (int i = 0; i <  NUM_DIRECTIVES; i++)
147         {       
148                 LRESULT index = SendMessage(hProps, CB_ADDSTRING, 0, (LPARAM) (LPWSTR) directive[i].name.c_str());
149                 LRESULT debug = SendMessage(hProps, CB_SETITEMDATA, (WPARAM)index, (LPARAM)i );
150         }
151         
152         LRESULT debug = SendMessage(hProps, CB_SETCURSEL, 0, 0);        // wparam = index, lparam = not used
153         
154 }
155
156 BOOL Shib_PropSheet::UpdateNewValue() {
157         _TCHAR value[MAX_REG_BUFF];
158         
159         DWORD index = SendMessage(hProps, CB_GETCURSEL, 0,0); 
160         UINT i = SendMessage(hProps, CB_GETITEMDATA, (WPARAM)index, 0 );
161         
162         if (directive[i].type == D_BOUND_INT || directive[i].type == D_BOUND_STRING) {
163                 index = SendMessage(hValueBox, CB_GETCURSEL, 0,0); 
164                 if (index == CB_ERR) { return FALSE; }
165                 LRESULT debug = SendMessage(hValueBox, CB_GETLBTEXT, (WPARAM)index, (LPARAM)value );
166         } else {
167                 LRESULT debug = SendMessage(hValueEdit, WM_GETTEXT, (WPARAM)MAX_REG_BUFF, (LPARAM)value );
168         }
169         
170         directive[i].new_value = value;
171         if (!_tcsicmp(directive[i].value.c_str(),value)) {
172                 return FALSE;
173         } else {
174                 return TRUE;
175         }
176 }
177
178 void Shib_PropSheet::GetHandles() {
179         hValueBox       = GetDlgItem(hwndDlg, IDC_ValueBox);
180         hValueEdit      = GetDlgItem(hwndDlg, IDC_ValueEdit);
181         hInheritedFrom  = GetDlgItem(hwndDlg, IDC_InheritedFrom);
182         hMoreInfo       = GetDlgItem(hwndDlg, IDC_MoreInfo);
183         hProps          = GetDlgItem(hwndDlg, IDC_PROPS);
184         hDelete         = GetDlgItem(hwndDlg, IDC_Delete);
185 }
186
187 void Shib_PropSheet::PopulatePage() {
188         
189         DWORD index = SendMessage(hProps, CB_GETCURSEL, 0,0); 
190         LRESULT i = SendMessage(hProps, CB_GETITEMDATA, (WPARAM)index, 0 );
191         
192         Set_Delete_Button(i);
193
194         if (directive[i].type == D_BOUND_INT || directive[i].type == D_BOUND_STRING) {
195                 ShowWindow(hValueEdit,SW_HIDE);
196                 ShowWindow(hValueBox,SW_SHOW);
197                 SendMessage(hValueBox,CB_RESETCONTENT,0,0);
198                 for(int vi=0;vi < NUM_BOUND_VAL;vi++) {
199                         if (directive[i].bound_val[vi].length()) {
200                                 LRESULT index = SendMessage(hValueBox, CB_INSERTSTRING, -1, (LPARAM) (LPWSTR) directive[i].bound_val[vi].c_str());
201                         }
202                 }
203                 
204                 SendMessage(hValueBox, WM_SETTEXT, 0, (LPARAM) directive[i].new_value.c_str());
205         } else {
206                 ShowWindow(hValueEdit,SW_SHOW);
207                 ShowWindow(hValueBox,SW_HIDE);
208                 SendMessage(hValueEdit, WM_SETTEXT, 0, (LPARAM) directive[i].new_value.c_str());
209         }
210         
211         SendMessage(hMoreInfo, WM_SETTEXT, 0, (LPARAM) directive[i].description.c_str());
212         SendMessage(hInheritedFrom, WM_SETTEXT, 0, (LPARAM) directive[i].defined_in.c_str());
213         
214 }
215
216 void Shib_PropSheet::DeleteValue() {
217
218         DWORD index = SendMessage(hProps, CB_GETCURSEL, 0,0); 
219         LRESULT i = SendMessage(hProps, CB_GETITEMDATA, (WPARAM)index, 0 );
220
221         directive[i].DeleteValue();
222
223 }
224
225 void Shib_PropSheet::SetupPropSheet() {
226
227         GetHandles();
228         ReadCurrentValues();
229         PopulateComboBox();     
230         PopulatePage();
231
232 }
233
234 BOOL CALLBACK Shib_PropSheet::DialogProc(
235                                                                                  HWND hwndDlg,  // handle to dialog box
236                                                                                  UINT uMsg,     // message
237                                                                                  WPARAM wParam, // first message parameter
238                                                                                  LPARAM lParam  // second message parameter
239                                                                                  )
240 {
241         
242         if (uMsg == WM_INITDIALOG) {
243                 Shib_PropSheet *pThis=reinterpret_cast<Shib_PropSheet *>(reinterpret_cast<PROPSHEETPAGE *>(lParam)->lParam);
244                 pThis->hwndDlg=hwndDlg;                              //store property page handle in class
245                 SetWindowLongPtr(hwndDlg,DWLP_USER,(LONG_PTR)pThis); //store class pointer in property page
246                 pThis->SetupPropSheet();
247         } else { 
248                 Shib_PropSheet *pThis = reinterpret_cast<Shib_PropSheet *>(reinterpret_cast<PROPSHEETPAGE *>(GetWindowLongPtr(hwndDlg,DWLP_USER)));  //retrieve class pointer from property page
249                 switch (uMsg) {
250                 case WM_COMMAND:
251                         if (HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == CBN_SELCHANGE) {
252                                 if ((HWND)lParam == GetDlgItem(hwndDlg,IDC_PROPS)) {  //if the user changes directives
253                                         pThis->PopulatePage();  //redraw page
254                                 } else {
255                                         if (pThis->UpdateNewValue()) {
256                                                 //if anything else changes, light the apply button
257                                                 SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); 
258                                         }
259                                 }
260                         }
261                         if (wParam == IDC_Delete) { 
262                                 pThis->DeleteValue();
263                                 pThis->PopulatePage();
264                                 SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); //light apply
265                         } else if (wParam == IDC_Refresh) {
266                                 pThis->ReadCurrentValues(); //refresh values
267                                 pThis->PopulatePage();      //refresh page
268                         }
269                         break;
270                         
271                 case WM_DESTROY:
272                         break;
273                         
274                 case WM_NOTIFY:
275                         switch (((NMHDR *) lParam)->code) {
276                         case PSN_APPLY:
277                                 pThis->UpdateNewValue();    //collect last-minute changes
278                                 pThis->WriteValues();       //write new values
279                                 pThis->ReadCurrentValues(); //refresh values
280                                 pThis->PopulatePage();      //refresh page
281                                 return PSNRET_NOERROR;
282                         }
283                         break;
284                 }
285         }
286         return FALSE;  //Seems to not fall through to parent page if you use DefWindowProc
287         //return DefWindowProc(hwndDlg, uMsg, wParam, lParam);
288 }
289
290 ///////////////////////////////
291 // Interface IExtendPropertySheet
292 ///////////////////////////////
293 HRESULT Shib_PropSheet::CreatePropertyPages( 
294                                                                                         /* [in] */ LPPROPERTYSHEETCALLBACK lpProvider,
295                                                                                         /* [in] */ LONG_PTR handle,
296                                                                                         /* [in] */ LPDATAOBJECT lpIDataObject)
297 {
298         PROPSHEETPAGE psp;
299         HPROPSHEETPAGE hPage = NULL;
300         
301         // cache this handle so we can call MMCPropertyChangeNotify
302         m_ppHandle = handle;
303         
304         UINT s_cfInstance =
305                 RegisterClipboardFormat(_T("ISM_SNAPIN_INSTANCE"));
306         UINT s_cfMachineName =
307                 RegisterClipboardFormat(_T("ISM_SNAPIN_MACHINE_NAME"));
308         UINT s_cfMetaPath =
309                 RegisterClipboardFormat(_T("ISM_SNAPIN_META_PATH"));
310         UINT s_cfNode =
311                 RegisterClipboardFormat(_T("ISM_SNAPIN_NODE"));
312         UINT s_cfParentPath =
313                 RegisterClipboardFormat(_T("ISM_SNAPIN_PARENT_PATH"));
314         UINT s_cfService =
315                 RegisterClipboardFormat(_T("ISM_SNAPIN_SERVICE"));
316         
317         if ( !lpProvider || !lpIDataObject )
318                 return E_POINTER;
319         
320         HRESULT hr = S_OK;
321         
322         DWORD dwLength = MAX_PATH * sizeof(_TCHAR);
323         DWORD dwWLength = MAX_PATH * sizeof(wchar_t);
324         
325         LPWSTR pwztInstance = reinterpret_cast<LPWSTR>(::LocalAlloc(LPTR, dwWLength));
326         LPWSTR pwztMachineName = reinterpret_cast<LPWSTR>(::LocalAlloc(LPTR, dwWLength));
327         LPWSTR pwztMetaPath = reinterpret_cast<LPWSTR>(::LocalAlloc(LPTR, dwWLength));
328         LPWSTR pwztNode = reinterpret_cast<LPWSTR>(::LocalAlloc(LPTR, dwWLength));
329         LPWSTR pwztParentPath = reinterpret_cast<LPWSTR>(::LocalAlloc(LPTR, dwWLength));
330         LPWSTR pwztService = reinterpret_cast<LPWSTR>(::LocalAlloc(LPTR, dwWLength));
331
332         if ( pwztInstance )
333                 Shib_PropSheet::ExtractWString(lpIDataObject, s_cfInstance, pwztInstance, dwLength);
334         if ( pwztMachineName )
335                 Shib_PropSheet::ExtractWString(lpIDataObject, s_cfMachineName, pwztMachineName, dwLength);
336         if ( pwztMetaPath )
337                 Shib_PropSheet::ExtractWString(lpIDataObject, s_cfMetaPath, pwztMetaPath, dwLength);
338         if ( pwztNode )
339                 Shib_PropSheet::ExtractWString(lpIDataObject, s_cfNode, pwztNode, dwLength);
340         if ( pwztParentPath )
341                 Shib_PropSheet::ExtractWString(lpIDataObject, s_cfParentPath, pwztParentPath, dwLength);
342         if ( pwztService )
343                 Shib_PropSheet::ExtractWString(lpIDataObject, s_cfService, pwztService, dwLength);
344
345         /* IIS only supports Unicode clipboard formats */
346 #ifdef _UNICODE
347         pwzInstance = pwztInstance;
348         pwzMachineName = pwztMachineName;
349         pwzMetaPath = pwztMetaPath;
350         pwzNode = pwztNode;
351         pwzParentPath = pwztParentPath;
352         pwzService = pwztService;
353 #else
354         pwzInstance = reinterpret_cast<LPSTR>(::LocalAlloc(LPTR, dwLength));
355         pwzMachineName = reinterpret_cast<LPSTR>(::LocalAlloc(LPTR, dwLength));
356         pwzMetaPath = reinterpret_cast<LPSTR>(::LocalAlloc(LPTR, dwLength));
357         pwzNode = reinterpret_cast<LPSTR>(::LocalAlloc(LPTR, dwLength));
358         pwzParentPath = reinterpret_cast<LPSTR>(::LocalAlloc(LPTR, dwLength));
359         pwzService = reinterpret_cast<LPSTR>(::LocalAlloc(LPTR, dwLength));
360
361         UnicodeToAnsi(pwztInstance,&pwzInstance);
362         UnicodeToAnsi(pwztMachineName,&pwzMachineName);
363         UnicodeToAnsi(pwztMetaPath,&pwzMetaPath);
364         UnicodeToAnsi(pwztNode,&pwzNode);
365         UnicodeToAnsi(pwztParentPath,&pwzParentPath);
366         UnicodeToAnsi(pwztService,&pwzService);
367
368         if ( pwztService )
369                 ::LocalFree(pwztService); 
370         if ( pwztParentPath )
371                 ::LocalFree(pwztParentPath);
372         if ( pwztNode )
373                 ::LocalFree(pwztNode);
374         if ( pwztMetaPath )
375                 ::LocalFree(pwztMetaPath);
376         if ( pwztMachineName )
377                 ::LocalFree(pwztMachineName);
378         if ( pwztInstance )
379                 ::LocalFree(pwztInstance);
380
381 #endif
382
383         for (int i=0;i<NUM_DIRECTIVES;i++) {
384                 directive[i].MachineName = pwzMachineName; 
385         }
386         pwzRegPath = reinterpret_cast<LPTSTR>(::LocalAlloc(LPTR, (dwLength*2)+1));
387         
388         LPTSTR ppath = _tcschr(pwzParentPath,_T('/'));
389         if (ppath) {
390                 StringCbCopy(pwzRegPath, MAX_PATH*2 ,ppath+1);
391                 StringCbCat (pwzRegPath, MAX_PATH*2 ,_T("/"));
392         } else {
393                 pwzRegPath[0] = 0;
394         }
395         StringCbCat(pwzRegPath, MAX_PATH*2 ,pwzNode);
396         
397         psp.dwSize = sizeof(PROPSHEETPAGE);
398         psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEICONID;
399         psp.hInstance = g_hinst;
400         psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE);
401         psp.pfnDlgProc = DialogProc;
402         psp.lParam = reinterpret_cast<LPARAM>(this);
403         psp.pszTitle = MAKEINTRESOURCE(IDS_PST_TAB_NAME);
404         
405         hPage = CreatePropertySheetPage(&psp);
406         _ASSERT(hPage);
407         
408         hr = lpProvider->AddPage(hPage);
409         
410         return hr;
411 }
412
413 HRESULT Shib_PropSheet::QueryPagesFor( 
414                                                                           /* [in] */ LPDATAOBJECT lpDataObject)
415 {
416         return S_OK;
417 }
418
419 void Shib_PropSheet::Set_Delete_Button(int i) {
420
421         if (!_tcsicmp((directive[i].defined_in.c_str() + 1),pwzRegPath)) {
422                 EnableWindow(hDelete,TRUE);
423         } else {
424                 EnableWindow(hDelete,FALSE);
425         }
426 }
427
428 void Shib_PropSheet::ReadSelectedValue() {
429
430         DWORD index = SendMessage(hProps, CB_GETCURSEL, 0,0); 
431         unsigned int i = SendMessage(hProps, CB_GETITEMDATA, (WPARAM)index, 0 );
432         directive[i].Set_Path(pwzRegPath);
433         directive[i].new_value = directive[i].value;
434
435 }
436
437 void Shib_PropSheet::ReadCurrentValues() {
438
439         for (int i=0;i<NUM_DIRECTIVES;i++) {
440                 directive[i].Set_Path(pwzRegPath);
441                 directive[i].new_value = directive[i].value;
442         }
443 }
444
445
446 void Shib_PropSheet::WriteValues() {
447         string RegPath;
448
449         RegPath = _T(SHIB_DEFAULT_WEB_KEY);
450
451         if  (_tcslen(pwzRegPath)) {
452                 RegPath += _T("\\");
453                 RegPath += pwzRegPath;
454                 ReplaceSlashes(RegPath);
455         } 
456         
457         for (int i=0;i<NUM_DIRECTIVES;i++) {
458                 if (_tcscmp(STR_PENDING_DELETION,directive[i].new_value.c_str())){
459                         if (_tcsicmp(directive[i].value.c_str(),directive[i].new_value.c_str())) {
460                                 directive[i].WriteValue(RegPath);
461                         }
462                 } else { // Commit Delete
463                         directive[i].DeleteRegVal(RegPath);
464                 }
465         }
466 }
467