Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
7.7 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Windows NT Directory Service Property Pages
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: notify.h
  9. //
  10. // Contents: Change notification ref-counting object.
  11. //
  12. // Classes: CNotifyObj
  13. //
  14. // History: 20-Jan-98 EricB
  15. //
  16. //-----------------------------------------------------------------------------
  17. /*+----------------------------------------------------------------------------
  18. Property page startup and communication architecture
  19. Caller creates a data object with the DSOBJECTNAMES clip format which names
  20. the DS object. Caller then creates the CLSID_DsPropertyPages object and passes
  21. in the data object pointer with the call to IShellExtInit::Initialize. The
  22. object that implements this class is known as the tab collector. It is in
  23. dsuiext.dll
  24. The caller then calls IShellPropSheetExt::AddPages. The tab collector's
  25. AddPages code reads the Display Specifier for the DS object's class. The
  26. Display Specifier lists the CLSIDs for the COM objects that implement the
  27. pages. AddPages then does a create on each CLSID, and for each calling the
  28. Initialize and AddPages methods.
  29. This iteration of the AddPages method is implemented by the CDsPropPagesHost
  30. class. The host class reads a table to determine the pages to create for this
  31. CLSID. Each page is created (via CreatePropertySheetPage) in the AddPages
  32. method and the page handle is passed back to the original caller via the
  33. AddPages callback parameter. The original caller builds an array of pages
  34. handles and creates the sheet once its call of AddPages returns.
  35. A mechanism is needed for operations that span all the pages of a sheet. These
  36. operations include
  37. a) binding to the DS object and retrieving the set of attributes that are
  38. needed by all pages,
  39. b) handling errors due to the inability to bind to or fetch attributes from an
  40. object,
  41. c) firing a single change notification back to the caller when an Apply is
  42. made,
  43. d) responding to queries for sheet exclusivity,
  44. e) sending a notification back to the caller when the sheet is closed.
  45. The number and order of pages in a sheet is determined by the set of CLSIDs in
  46. the display specifier. The display specifier is user modifiable. Because of
  47. this, a hard-coded scheme that makes assumptions about the order and number of
  48. pages cannot be used for the page-spanning operations enumerated above. Thus a
  49. separate object, called the notification object, is created at sheet creation
  50. time. The pages communicate with the notification object using window messages.
  51. The notification object has a hidden window, a window proceedure, and a message
  52. pump running on its own thread.
  53. One then must ask: when does the notification window get created and when is it
  54. destroyed? The creation will be in CDsPropPagesHost's implementation of
  55. Initialize. The destruction will be signalled by a send message from the pages'
  56. callback function.
  57. The notify creation function will do a FindWindow looking for the notification
  58. window. If not found, it will create it. During the notify object's creation it
  59. will bind to the DS object and request the cn and allowedAttributesEffective
  60. properties. The window's handle will then be returned to the Initialize
  61. function so that the resultant pages can communicate with it. If the
  62. notification object/window cannot be created, then an error will be returned
  63. to the Initialize method which will in turn return the error to the original
  64. caller. The caller should then abort the property display and should report a
  65. catastrophic failure to the user. If the notification object is successfully
  66. created, but the initial attributes cannot be fetched from the DS object, then
  67. an internal error variable will be set in the notify object although it's
  68. creation function will return a success code.
  69. As the individual pages initialize, they will send a message asking for the
  70. ADSI object pointer, the CN, and the effective-attributes list. An error code
  71. will be returned instead if the bind/fetch failed. The page init code will
  72. report this error to the user by substituting an error page for the property
  73. page. This is done at page object initialization time (CDsPropPageBase::Init).
  74. This is before the CreatePropertySheetPage call is made allowing the
  75. substitution of an error page.
  76. typedef struct {
  77. DWORD dwSize; // Set this to the size of the struct.
  78. DWORD dwFlags; // Reserved for future use.
  79. HRESULT hr; // If this is non-zero, then the others
  80. IDirectoryObject * pDsObj; // should be ignored.
  81. LPCWSTR pwzCN;
  82. PADS_ATTR_INFO pWritableAttrs;
  83. } ADSPROPINITPARAMS, * PADSPROPINITPARAMS;
  84. #define WM_ADSPROP_NOTIFY_PAGEINIT
  85. // where LPARAM is the PADSPROPINITPARAMS pointer.
  86. Each page checks its list of attributes against those in the
  87. allowedAttributesEffective array. If an attribute is found in the allowed
  88. list, then it is marked as writable and its corresponding control will be
  89. enabled. If an attribute is set to be un-readable but writable for that user
  90. (an unusual but legal situation), the LDAP read will silently fail so that no
  91. value will be placed in the dialog control, but the control will be left
  92. enabled. Thus the user could unwittingly overwrite an existing value.
  93. Consequently it is not a good idea to grant a user write permission but revoke
  94. read permission on an attribute unless the above behavior is explicitly
  95. intended. Here is the struct that will be used to mark attributes as
  96. writable:
  97. typedef struct {
  98. BOOL fWritable;
  99. PVOID pAttrData;
  100. } ATTR_DATA, * PATTR_DATA;
  101. An array of these structures will be allocated for each page with one element
  102. per attribute. The ordering will be the same as the table of attributes for the
  103. page.
  104. Methods to check writability:
  105. HRESULT CDsPropPageBase::CheckIfWritable(PATTR_DATA rgAttrData,
  106. PATTR_MAP * rgAttrMap,
  107. DWORD cAttrs,
  108. PADS_ATTR_INFO pWritableAttrs);
  109. BOOL CDsPropPageBase::CheckIfWritable(const PWSTR & wzAttr);
  110. Another private message will be used to pass the page's window handle to the
  111. notify object. The notify object needs to know the property sheet's window
  112. handle, which it can get by calling GetParent on the passed page handle. This
  113. message is sent by each page's WM_DLGINIT function. The notify object's page
  114. count will be incremented at this time.
  115. #define WM_ADSPROP_NOTIFY_PAGEHWND
  116. // where WPARAM => page's HWND
  117. -----------------------------------------------------------------------------*/
  118. #ifndef _NOTIFY_H_
  119. #define _NOTIFY_H_
  120. #include <propcfg.h> // DS Admin definition of PPROPSHEETCFG
  121. #include <adsprop.h>
  122. const TCHAR tzNotifyWndClass[] = TEXT("DsPropNotifyWindow");
  123. #define DSPROP_TITLE_LEN 16
  124. extern "C" BOOL IsSheetAlreadyUp(LPDATAOBJECT);
  125. extern "C" BOOL BringSheetToForeground(PWSTR, BOOL);
  126. VOID __cdecl NotifyThreadFcn(PVOID);
  127. BOOL FindSheet(PWSTR);
  128. HWND FindSheetNoSetFocus(PWSTR);
  129. VOID RegisterNotifyClass(void);
  130. #ifndef DSPROP_ADMIN
  131. //+----------------------------------------------------------------------------
  132. //
  133. // Class: CNotifyCreateCriticalSection
  134. //
  135. // Purpose: Prevents creation race conditions. Without this protection,
  136. // a second call to CNotifyObj::Create that comes in before the
  137. // first has created the hidden window will get NULL back from
  138. // FindSheetNoSetFocus and then go on to create a second hidden
  139. // window.
  140. //
  141. //-----------------------------------------------------------------------------
  142. class CNotifyCreateCriticalSection
  143. {
  144. public:
  145. CNotifyCreateCriticalSection();
  146. ~CNotifyCreateCriticalSection();
  147. };
  148. #endif // DSPROP_ADMIN
  149. #endif // _NOTIFY_H_