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.

354 lines
11 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: getpbk.cpp
  4. //
  5. // Module: Common Code
  6. //
  7. // Synopsis: Implements the function GetPhoneBookPath.
  8. //
  9. // Copyright (c) 1999 Microsoft Corporation
  10. //
  11. // Author: quintinb Created Heaser 08/19/99
  12. //
  13. //+----------------------------------------------------------------------------
  14. //+----------------------------------------------------------------------------
  15. //
  16. // Function: AllocateSecurityDescriptorAllowAccessToWorld
  17. //
  18. // Synopsis: This function allocates a security descriptor for all users.
  19. // This function was taken directly from RAS when they create their
  20. // phonebook. This has to be before GetPhoneBookPath otherwise it
  21. // causes compile errors in other components since we don't have a
  22. // function prototype anywhere and cmcfg just includes this (getpbk.cpp)
  23. // file. This function is also in cmdial\ras.cpp
  24. //
  25. // Arguments: PSECURITY_DESCRIPTOR *ppSd - Pointer to a pointer to the SD struct
  26. //
  27. // Returns: DWORD - returns ERROR_SUCCESS if successfull
  28. //
  29. // History: 06/27/2001 tomkel Taken from RAS ui\common\pbk\file.c
  30. //
  31. //+----------------------------------------------------------------------------
  32. #define SIZE_ALIGNED_FOR_TYPE(_size, _type) \
  33. (((_size) + sizeof(_type)-1) & ~(sizeof(_type)-1))
  34. DWORD AllocateSecurityDescriptorAllowAccessToWorld(PSECURITY_DESCRIPTOR *ppSd)
  35. {
  36. PSECURITY_DESCRIPTOR pSd;
  37. PSID pSid;
  38. PACL pDacl;
  39. DWORD dwErr = ERROR_SUCCESS;
  40. DWORD dwAlignSdSize;
  41. DWORD dwAlignDaclSize;
  42. DWORD dwSidSize;
  43. PVOID pvBuffer;
  44. DWORD dwAcls = 0;
  45. // Here is the buffer we are building.
  46. //
  47. // |<- a ->|<- b ->|<- c ->|
  48. // +-------+--------+------+
  49. // | p| p| |
  50. // | SD a| DACL a| SID |
  51. // | d| d| |
  52. // +-------+-------+-------+
  53. // ^ ^ ^
  54. // | | |
  55. // | | +--pSid
  56. // | |
  57. // | +--pDacl
  58. // |
  59. // +--pSd (this is returned via *ppSd)
  60. //
  61. // pad is so that pDacl and pSid are aligned properly.
  62. //
  63. // a = dwAlignSdSize
  64. // b = dwAlignDaclSize
  65. // c = dwSidSize
  66. //
  67. if (NULL == ppSd)
  68. {
  69. return ERROR_INVALID_PARAMETER;
  70. }
  71. // Initialize output parameter.
  72. //
  73. *ppSd = NULL;
  74. // Compute the size of the SID. The SID is the well-known SID for World
  75. // (S-1-1-0).
  76. //
  77. dwSidSize = GetSidLengthRequired(1);
  78. // Compute the size of the DACL. It has an inherent copy of SID within
  79. // it so add enough room for it. It also must sized properly so that
  80. // a pointer to a SID structure can come after it. Hence, we use
  81. // SIZE_ALIGNED_FOR_TYPE.
  82. //
  83. dwAlignDaclSize = SIZE_ALIGNED_FOR_TYPE(
  84. sizeof(ACCESS_ALLOWED_ACE) + sizeof(ACL) + dwSidSize,
  85. PSID);
  86. // Compute the size of the SD. It must be sized propertly so that a
  87. // pointer to a DACL structure can come after it. Hence, we use
  88. // SIZE_ALIGNED_FOR_TYPE.
  89. //
  90. dwAlignSdSize = SIZE_ALIGNED_FOR_TYPE(
  91. sizeof(SECURITY_DESCRIPTOR),
  92. PACL);
  93. // Allocate the buffer big enough for all.
  94. //
  95. dwErr = ERROR_OUTOFMEMORY;
  96. pvBuffer = CmMalloc(dwSidSize + dwAlignDaclSize + dwAlignSdSize);
  97. if (pvBuffer)
  98. {
  99. SID_IDENTIFIER_AUTHORITY SidIdentifierWorldAuth
  100. = SECURITY_WORLD_SID_AUTHORITY;
  101. PULONG pSubAuthority;
  102. dwErr = NOERROR;
  103. // Setup the pointers into the buffer.
  104. //
  105. pSd = pvBuffer;
  106. pDacl = (PACL)((PBYTE)pvBuffer + dwAlignSdSize);
  107. pSid = (PSID)((PBYTE)pDacl + dwAlignDaclSize);
  108. // Initialize pSid as S-1-1-0.
  109. //
  110. if (!InitializeSid(
  111. pSid,
  112. &SidIdentifierWorldAuth,
  113. 1)) // 1 sub-authority
  114. {
  115. dwErr = GetLastError();
  116. goto finish;
  117. }
  118. pSubAuthority = GetSidSubAuthority(pSid, 0);
  119. *pSubAuthority = SECURITY_WORLD_RID;
  120. // Initialize pDacl.
  121. //
  122. if (!InitializeAcl(
  123. pDacl,
  124. dwAlignDaclSize,
  125. ACL_REVISION))
  126. {
  127. dwErr = GetLastError();
  128. goto finish;
  129. }
  130. dwAcls = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
  131. dwAcls &= ~(WRITE_DAC | WRITE_OWNER);
  132. if(!AddAccessAllowedAce(
  133. pDacl,
  134. ACL_REVISION,
  135. dwAcls,
  136. pSid))
  137. {
  138. dwErr = GetLastError();
  139. goto finish;
  140. }
  141. // Initialize pSd.
  142. //
  143. if (!InitializeSecurityDescriptor(
  144. pSd,
  145. SECURITY_DESCRIPTOR_REVISION))
  146. {
  147. dwErr = GetLastError();
  148. goto finish;
  149. }
  150. // Set pSd to use pDacl.
  151. //
  152. if (!SetSecurityDescriptorDacl(
  153. pSd,
  154. TRUE,
  155. pDacl,
  156. FALSE))
  157. {
  158. dwErr = GetLastError();
  159. goto finish;
  160. }
  161. // Set the owner for pSd.
  162. //
  163. if (!SetSecurityDescriptorOwner(
  164. pSd,
  165. NULL,
  166. TRUE))
  167. {
  168. dwErr = GetLastError();
  169. goto finish;
  170. }
  171. // Set the group for pSd.
  172. //
  173. if (!SetSecurityDescriptorGroup(
  174. pSd,
  175. NULL,
  176. FALSE))
  177. {
  178. dwErr = GetLastError();
  179. goto finish;
  180. }
  181. finish:
  182. if (!dwErr)
  183. {
  184. *ppSd = pSd;
  185. }
  186. else
  187. {
  188. CmFree(pvBuffer);
  189. }
  190. }
  191. return dwErr;
  192. }
  193. //+----------------------------------------------------------------------------
  194. //
  195. // Function: GetPhoneBookPath
  196. //
  197. // Synopsis: This function will return the proper path to the phonebook. If
  198. // used on a legacy platform this is NULL. On NT5, the function
  199. // depends on the proper Install Directory being inputted so that
  200. // the function can use this as a base to determine the phonebook path.
  201. // If the inputted pointer to a string buffer is filled with a path,
  202. // then the directory path will be created as will the pbk file itself.
  203. // The caller should always call CmFree on the pointer passed into this
  204. // API when done with the path, because it will either free the memory
  205. // or do nothing (NULL case).
  206. //
  207. // Arguments: LPCTSTR pszInstallDir - path to the CM profile dir
  208. // LPTSTR* ppszPhoneBook - pointer to accept a newly allocated and filled pbk string
  209. // BOOL fAllUser - TRUE if this an All-User profile
  210. //
  211. // Returns: BOOL - returns TRUE if successful
  212. //
  213. // History: quintinb Created 11/12/98
  214. // tomkel 06/28/2001 Changed the ACLs when the phonebook gets
  215. // createdfor an All-User profile
  216. //
  217. //+----------------------------------------------------------------------------
  218. BOOL GetPhoneBookPath(LPCTSTR pszInstallDir, LPTSTR* ppszPhonebook, BOOL fAllUser)
  219. {
  220. if (NULL == ppszPhonebook)
  221. {
  222. CMASSERTMSG(FALSE, TEXT("GetPhoneBookPath -- Invalid Parameter"));
  223. return FALSE;
  224. }
  225. CPlatform plat;
  226. if (plat.IsAtLeastNT5())
  227. {
  228. if ((NULL == pszInstallDir) || (TEXT('\0') == pszInstallDir[0]))
  229. {
  230. CMASSERTMSG(FALSE, TEXT("GetPhoneBookPath -- Invalid Install Dir parameter."));
  231. return FALSE;
  232. }
  233. //
  234. // Now Create the path to the phonebook.
  235. //
  236. LPTSTR pszPhonebook;
  237. TCHAR szInstallDir[MAX_PATH+1];
  238. ZeroMemory(szInstallDir, CELEMS(szInstallDir));
  239. if (TEXT('\\') == pszInstallDir[lstrlen(pszInstallDir) - 1])
  240. {
  241. //
  242. // Then the path ends in a backslash. Thus we won't properly
  243. // remove CM from the path. Remove the backslash.
  244. //
  245. lstrcpyn(szInstallDir, pszInstallDir, lstrlen(pszInstallDir));
  246. }
  247. else
  248. {
  249. lstrcpy(szInstallDir, pszInstallDir);
  250. }
  251. CFileNameParts InstallDirPath(szInstallDir);
  252. pszPhonebook = (LPTSTR)CmMalloc(lstrlen(InstallDirPath.m_Drive) +
  253. lstrlen(InstallDirPath.m_Dir) +
  254. lstrlen(c_pszPbk) + lstrlen(c_pszRasPhonePbk) + 1);
  255. if (NULL != pszPhonebook)
  256. {
  257. wsprintf(pszPhonebook, TEXT("%s%s%s"), InstallDirPath.m_Drive,
  258. InstallDirPath.m_Dir, c_pszPbk);
  259. //
  260. // Use CreateLayerDirectory to recursively create the directory structure as
  261. // necessary (will create all the directories in a full path if necessary).
  262. //
  263. MYVERIFY(FALSE != CreateLayerDirectory(pszPhonebook));
  264. MYVERIFY(NULL != lstrcat(pszPhonebook, c_pszRasPhonePbk));
  265. HANDLE hPbk = INVALID_HANDLE_VALUE;
  266. SECURITY_ATTRIBUTES sa = {0};
  267. PSECURITY_ATTRIBUTES pSA = NULL;
  268. PSECURITY_DESCRIPTOR pSd = NULL;
  269. if (fAllUser)
  270. {
  271. //
  272. // For an All-User profile be sure to create it with a
  273. // security descriptor that allows it to be read by any authenticated
  274. // user. If we don't it may prevent other users from being able to
  275. // read it. We didn't want to change the old behavior downlevel so this
  276. // fix is just for Whistler+.
  277. //
  278. DWORD dwErr = AllocateSecurityDescriptorAllowAccessToWorld(&pSd);
  279. if ((ERROR_SUCCESS == dwErr) && pSd)
  280. {
  281. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  282. sa.lpSecurityDescriptor = pSd;
  283. sa.bInheritHandle = TRUE;
  284. pSA = &sa;
  285. }
  286. }
  287. hPbk = CreateFile(pszPhonebook, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, pSA, CREATE_NEW,
  288. FILE_ATTRIBUTE_NORMAL, NULL);
  289. CmFree(pSd);
  290. if (hPbk != INVALID_HANDLE_VALUE)
  291. {
  292. MYVERIFY(0 != CloseHandle(hPbk));
  293. }
  294. *ppszPhonebook = pszPhonebook;
  295. }
  296. else
  297. {
  298. CMASSERTMSG(FALSE, TEXT("CmMalloc returned NULL"));
  299. return FALSE;
  300. }
  301. }
  302. else
  303. {
  304. *ppszPhonebook = NULL;
  305. }
  306. return TRUE;
  307. }