Leaked source code of windows server 2003
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.

654 lines
20 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File Name: fxocUtil.cpp
  4. //
  5. // Abstract: This provides the utility routines used in the FaxOCM
  6. // code base.
  7. //
  8. // Environment: Windows XP / User Mode
  9. //
  10. // Copyright (c) 2000 Microsoft Corporation
  11. //
  12. // Revision History:
  13. //
  14. // Date: Developer: Comments:
  15. // ----- ---------- ---------
  16. // 21-Mar-2000 Oren Rosenbloom (orenr) Created
  17. //////////////////////////////////////////////////////////////////////////////
  18. // Project Includes
  19. #include "faxocm.h"
  20. // System Includes
  21. #include <lmshare.h>
  22. #include <lmaccess.h>
  23. #include <lmerr.h>
  24. #include <Aclapi.h> // For SetSecurityInfo
  25. #pragma hdrstop
  26. //////////////////////// Static Function Prototypes //////////////////////////
  27. ///////////////////////////////
  28. // fxocUtil_Init
  29. //
  30. // Initialize the misc. utilities
  31. // required by faxocm.dll.
  32. //
  33. // Params:
  34. // - void.
  35. // Returns:
  36. // - NO_ERROR on success.
  37. // - error code otherwise
  38. //
  39. DWORD fxocUtil_Init(void)
  40. {
  41. DWORD dwRes = NO_ERROR;
  42. DBG_ENTER(_T("Init Util module"),dwRes);
  43. return dwRes;
  44. }
  45. ///////////////////////////////
  46. // fxocUtil_Term
  47. //
  48. // Terminate the misc. utilities
  49. // required by faxocm.dll
  50. //
  51. // Params:
  52. // - void.
  53. // Returns:
  54. // - NO_ERROR on success.
  55. // - error code otherwise.
  56. //
  57. DWORD fxocUtil_Term(void)
  58. {
  59. DWORD dwRes = NO_ERROR;
  60. DBG_ENTER(_T("Term Util module"),dwRes);
  61. return dwRes;
  62. }
  63. ///////////////////////////////
  64. // fxocUtil_GetUninstallSection
  65. //
  66. // Get field value in the INF
  67. // pointed to by the INF_KEYWORD_INSTALLTYPE_UNINSTALL
  68. // keyword.
  69. //
  70. // Params:
  71. // - pszSection - section to search for keyword in.
  72. // - pszValue - IN - buffer returning the value of the keyword
  73. // - dwNumBufChars - # of chars the pszValue buffer can hold
  74. //
  75. DWORD fxocUtil_GetUninstallSection(const TCHAR *pszSection,
  76. TCHAR *pszValue,
  77. DWORD dwNumBufChars)
  78. {
  79. DWORD dwReturn = NO_ERROR;
  80. DBG_ENTER(_T("fxocUtil_GetUninstallSection"),dwReturn,_T("%s"),pszSection);
  81. if ((pszSection == NULL) ||
  82. (pszValue == NULL) ||
  83. (dwNumBufChars == 0))
  84. {
  85. return ERROR_INVALID_PARAMETER;
  86. }
  87. dwReturn = fxocUtil_GetKeywordValue(pszSection,
  88. INF_KEYWORD_INSTALLTYPE_UNINSTALL,
  89. pszValue,
  90. dwNumBufChars);
  91. return dwReturn;
  92. }
  93. ///////////////////////////////
  94. // fxocUtil_GetKeywordValue
  95. //
  96. // This is used for getting the
  97. // various Install/Uninstall
  98. // sections, dependent on if we
  99. // are a clean install, upgrade,
  100. // etc.
  101. //
  102. // The format in the INF will look like this:
  103. //
  104. // [Section]
  105. // Keyword = Value
  106. //
  107. // Params:
  108. // - pszSection - section to search for the keyword in.
  109. // - pszKeyword - keyword to get the value for.
  110. // - pszValue - OUT - buffer that will hold the keyword's value
  111. // - dwNumBufChars - # of characters the pszValue buffer can hold.
  112. // Returns:
  113. // - NO_ERROR on success.
  114. // - error code otherwise.
  115. //
  116. DWORD fxocUtil_GetKeywordValue(const TCHAR *pszSection,
  117. const TCHAR *pszKeyword,
  118. TCHAR *pszValue,
  119. DWORD dwNumBufChars)
  120. {
  121. HINF hInf = faxocm_GetComponentInf();
  122. DWORD dwReturn = NO_ERROR;
  123. BOOL bSuccess = FALSE;
  124. INFCONTEXT Context;
  125. DBG_ENTER( _T("fxocUtil_GetKeywordValue"),
  126. dwReturn,
  127. _T("%s - %s "),
  128. pszSection,
  129. pszKeyword);
  130. if ((pszSection == NULL) ||
  131. (pszKeyword == NULL) ||
  132. (pszValue == NULL) ||
  133. (dwNumBufChars == 0))
  134. {
  135. return ERROR_INVALID_PARAMETER;
  136. }
  137. bSuccess = ::SetupFindFirstLine(hInf,
  138. pszSection,
  139. pszKeyword,
  140. &Context);
  141. if (bSuccess)
  142. {
  143. bSuccess = ::SetupGetStringField(&Context,
  144. 1,
  145. pszValue,
  146. dwNumBufChars,
  147. NULL);
  148. if (!bSuccess)
  149. {
  150. dwReturn = ::GetLastError();
  151. VERBOSE(SETUP_ERR,
  152. _T("faxocm_GetKeywordValue, failed to get ")
  153. _T("keyword value for section '%s', ")
  154. _T("keyword '%s', rc = 0x%lx"),
  155. pszSection,
  156. pszKeyword,
  157. dwReturn);
  158. }
  159. }
  160. else
  161. {
  162. dwReturn = ::GetLastError();
  163. VERBOSE(SETUP_ERR,
  164. _T("faxocm_GetKeywordValue, failed to get ")
  165. _T("keyword value for component '%s', rc = 0x%lx"),
  166. pszSection,
  167. dwReturn);
  168. }
  169. return dwReturn;
  170. }
  171. ///////////////////////////////
  172. // fxocUtil_DoSetup
  173. //
  174. // Generic fn to create/delete program links
  175. //
  176. // Params:
  177. // - hInf - handle to INF file
  178. // - pszSection - section to install/uninstall from
  179. // - bInstall - TRUE if installing, FALSE if uninstalling
  180. // - pszFnName - name of calling fn (for debug).
  181. // Returns:
  182. // - NO_ERROR on success
  183. // - error code otherwise.
  184. //
  185. DWORD fxocUtil_DoSetup(HINF hInf,
  186. const TCHAR *pszSection,
  187. BOOL bInstall,
  188. DWORD dwFlags,
  189. const TCHAR *pszFnName)
  190. {
  191. DWORD dwReturn = NO_ERROR;
  192. BOOL bSuccess = FALSE;
  193. DBG_ENTER( _T("fxocUtil_DoSetup"),
  194. dwReturn,
  195. _T("%s - %s "),
  196. pszSection,
  197. pszFnName);
  198. if ((hInf == NULL) ||
  199. (pszSection == NULL))
  200. {
  201. return ERROR_INVALID_PARAMETER;
  202. }
  203. // This function call will install or uninstall the shortcuts depending
  204. // on the value of the "pszSection" parameter. If the section references
  205. // the install section, then the shortcuts will be installed, otherwise
  206. // they will be uninstalled.
  207. bSuccess = ::SetupInstallFromInfSection(NULL,
  208. hInf,
  209. pszSection,
  210. dwFlags,
  211. NULL, // relative key root
  212. NULL, // source root path
  213. 0, // copy flags
  214. NULL, // callback routine
  215. NULL, // callback routine context
  216. NULL, // device info set
  217. NULL); // device info struct
  218. if (!bSuccess)
  219. {
  220. dwReturn = ::GetLastError();
  221. VERBOSE(SETUP_ERR,
  222. _T("SetupInstallFromInfSection failed, rc = 0x%lx"),
  223. dwReturn);
  224. }
  225. return dwReturn;
  226. }
  227. //////////////////////////////////
  228. // fxocUtil_CreateNetworkShare
  229. //
  230. //
  231. // Create share on the current machine.
  232. // If the share name is already exist,
  233. // then the function will try to erase the share
  234. // and then create new one to lpctstrPath
  235. //
  236. // Params:
  237. // - const FAX_SHARE_Description* fsdShare - share description
  238. // Returns:
  239. // - Returns TRUE on success
  240. // - FALSE otherwise
  241. //
  242. BOOL fxocUtil_CreateNetworkShare(const FAX_SHARE_Description* fsdShare)
  243. {
  244. SHARE_INFO_502 ShareInfo502;
  245. NET_API_STATUS rVal = 0;
  246. DWORD dwShareType = 0;
  247. DWORD dwNumChars = 0;
  248. WCHAR szExpandedPath[MAX_PATH*2];
  249. DBG_ENTER(_T("fxocUtil_CreateNetworkShare"));
  250. ZeroMemory(&ShareInfo502, sizeof(SHARE_INFO_502));
  251. dwNumChars = ExpandEnvironmentStrings(fsdShare->szPath, szExpandedPath, sizeof(szExpandedPath)/sizeof(szExpandedPath[0]));
  252. if (dwNumChars == 0)
  253. {
  254. VERBOSE(SETUP_ERR,
  255. _T("ExpandEnvironmentStrings failed, rc = 0x%lx"),
  256. ::GetLastError());
  257. return FALSE;
  258. }
  259. ShareInfo502.shi502_netname = (LPTSTR)fsdShare->szName;
  260. ShareInfo502.shi502_type = STYPE_DISKTREE;
  261. ShareInfo502.shi502_remark = (LPTSTR)fsdShare->szComment;
  262. ShareInfo502.shi502_permissions = ACCESS_ALL;
  263. ShareInfo502.shi502_max_uses = (DWORD) -1,
  264. ShareInfo502.shi502_current_uses = (DWORD) -1;
  265. ShareInfo502.shi502_path = szExpandedPath;
  266. ShareInfo502.shi502_passwd = NULL;
  267. ShareInfo502.shi502_security_descriptor = fsdShare->pSD;
  268. rVal = ::NetShareAdd(NULL,
  269. 502,
  270. (LPBYTE) &ShareInfo502,
  271. NULL);
  272. if (rVal == NERR_Success)
  273. {
  274. VERBOSE(DBG_MSG, _T("Successfully added '%s' share."), fsdShare->szName);
  275. }
  276. else if (rVal == NERR_DuplicateShare)
  277. {
  278. // share by the same name was found, attempt to delete it, and re-add it.
  279. VERBOSE(SETUP_ERR,
  280. _T("The share %s already exist, (err=%ld) ")
  281. _T("CreateNetworkShare will try to remove the share and ")
  282. _T("re-create it."),
  283. fsdShare->szName,
  284. GetLastError());
  285. // delete duplicate share.
  286. rVal = ::NetShareDel(NULL,
  287. (LPTSTR) fsdShare->szName,
  288. 0);
  289. VERBOSE(DBG_MSG,
  290. _T("NetShareDel returned 0x%lx"),
  291. rVal);
  292. if (rVal != NERR_Success)
  293. {
  294. // failed to delete duplicate share.
  295. VERBOSE(SETUP_ERR,
  296. _T("NetShareDel failed to delete '%s' share, rc = 0x%lx,")
  297. _T("attempting to recreate it anyway"),
  298. fsdShare->szName,
  299. rVal);
  300. }
  301. // attempt to add new share, even if we failed to delete the duplicate share.
  302. // Hopefully this will work regardless of the delete failure.
  303. rVal = ::NetShareAdd(NULL,
  304. 502,
  305. (LPBYTE) &ShareInfo502,
  306. NULL);
  307. if (rVal == NERR_Success)
  308. {
  309. VERBOSE(DBG_MSG, _T("Successfully added '%s' share."), fsdShare->szName);
  310. }
  311. else
  312. {
  313. VERBOSE(SETUP_ERR,
  314. _T("Failed to add '%s' share on second attempt, ")
  315. _T("rc = 0x%lx"),
  316. rVal);
  317. ::SetLastError(rVal);
  318. }
  319. }
  320. else
  321. {
  322. ::SetLastError(rVal);
  323. }
  324. return (rVal == NERR_Success);
  325. }
  326. //////////////////////////////////
  327. // fxocUtil_DeleteNetworkShare
  328. //
  329. // Delete a share on the current machine.
  330. // Returns TRUE on success, FALSE otherwise
  331. //
  332. // Params:
  333. // - LPCWSTR lpcwstrShareName : : share name to delete
  334. // Returns:
  335. // - TRUE on Success
  336. // - FALSE otherwise
  337. //
  338. BOOL fxocUtil_DeleteNetworkShare(LPCWSTR pszShareName)
  339. {
  340. NET_API_STATUS rVal;
  341. DBG_ENTER( _T("fxocUtil_DeleteNetworkShare"),
  342. _T("%s"),
  343. pszShareName);
  344. rVal = NetShareDel(NULL, // Local computer's share
  345. (LPTSTR) pszShareName, // Name of the share to delete.
  346. 0);
  347. return (rVal == NERR_Success);
  348. }
  349. ///////////////////////////////////////////////////////////////////////////////////////
  350. // Function:
  351. // fxocUtil_SearchAndExecute
  352. //
  353. // Purpose:
  354. // Searches a specified INF section for keywords of the type 'pszSearchKey'
  355. // Each keyword should be in the format 'pszSearchKey' = platform, section to process.
  356. // If the platform matches, then the section is processed according to Flags
  357. // passed to SetupInstallFromInfSection
  358. //
  359. // Params:
  360. // const TCHAR* pszInstallSection - section to search in
  361. // const TCHAR* pszSearchKey - keyword to find
  362. // UINT Flags - flags to pass to SetupInstallFromInfSection
  363. // HSPFILEQ hQueue - handle to file queue, if specified, this function
  364. // will attemp to install files using the
  365. // SetupInstallFilesFromInfSection API
  366. //
  367. // Return Value:
  368. // NO_ERROR - in case of success
  369. // Win32 Error code - otherwise
  370. //
  371. // Author:
  372. // Mooly Beery (MoolyB) 02-Apr-2001
  373. ///////////////////////////////////////////////////////////////////////////////////////
  374. DWORD fxocUtil_SearchAndExecute
  375. (
  376. const TCHAR* pszInstallSection,
  377. const TCHAR* pszSearchKey,
  378. UINT Flags,
  379. HSPFILEQ hQueue
  380. )
  381. {
  382. DWORD dwReturn = NO_ERROR;
  383. INFCONTEXT Context;
  384. BOOL bNextSearchKeyFound = TRUE;
  385. HINF hInf = faxocm_GetComponentInf();
  386. DBG_ENTER(_T("fxocUtil_SearchAndExecute"),dwReturn,_T("%s - %s"),pszInstallSection,pszSearchKey);
  387. // let's look for 'pszSearchKey' directives
  388. bNextSearchKeyFound = ::SetupFindFirstLine( hInf,
  389. pszInstallSection,
  390. pszSearchKey,
  391. &Context);
  392. if (!bNextSearchKeyFound)
  393. {
  394. VERBOSE(DBG_WARNING,
  395. _T("Did not find '%s' keyword in ")
  396. _T("section '%s'. No action will be taken."),
  397. pszSearchKey,
  398. pszInstallSection);
  399. goto exit;
  400. }
  401. while (bNextSearchKeyFound)
  402. {
  403. // we have a CreateShortcut section.
  404. DWORD dwCount = ::SetupGetFieldCount(&Context);
  405. if (dwCount!=2)
  406. {
  407. VERBOSE(SETUP_ERR,_T("Invalid %s section, has %d param instead of 2"),pszSearchKey,dwCount);
  408. goto exit;
  409. }
  410. // get the platform specifier
  411. INT iPlatform = 0;
  412. if (!::SetupGetIntField(&Context, 1, &iPlatform))
  413. {
  414. dwReturn = GetLastError();
  415. VERBOSE(SETUP_ERR,_T("SetupGetStringField failed (ec=%d)"),dwReturn);
  416. goto exit;
  417. }
  418. // check the platform we read against the specifier
  419. if (iPlatform & GetProductSKU())
  420. {
  421. // we should process this section, get the section name
  422. TCHAR szSectionName[MAX_PATH] = {0};
  423. if (!::SetupGetStringField(&Context,2,szSectionName,MAX_PATH,NULL))
  424. {
  425. dwReturn = GetLastError();
  426. VERBOSE(SETUP_ERR,_T("SetupGetStringField failed (ec=%d)"),dwReturn);
  427. goto exit;
  428. }
  429. // check if a file operation was requested
  430. if (hQueue)
  431. {
  432. if (::SetupInstallFilesFromInfSection(hInf,NULL,hQueue,szSectionName,NULL,Flags))
  433. {
  434. VERBOSE(DBG_MSG,
  435. _T("Successfully queued files from Section: '%s'"),
  436. szSectionName);
  437. }
  438. else
  439. {
  440. dwReturn = GetLastError();
  441. VERBOSE(DBG_MSG,
  442. _T("Failed to queue files from Section: '%s', Error Code = 0x%lx"),
  443. szSectionName,
  444. dwReturn);
  445. }
  446. }
  447. else
  448. {
  449. if (::SetupInstallFromInfSection(NULL,hInf,szSectionName,Flags,NULL,NULL,0,NULL,NULL,NULL,NULL))
  450. {
  451. VERBOSE(DBG_MSG,
  452. _T("Successfully installed from INF file, section '%s'"),
  453. szSectionName);
  454. }
  455. else
  456. {
  457. dwReturn = GetLastError();
  458. VERBOSE(SETUP_ERR,
  459. _T("Failed to install from INF file, section '%s', dwReturn = 0x%lx"),
  460. szSectionName,
  461. dwReturn);
  462. }
  463. }
  464. }
  465. // get the next section.
  466. bNextSearchKeyFound = ::SetupFindNextMatchLine( &Context,
  467. pszSearchKey,
  468. &Context);
  469. if (!bNextSearchKeyFound)
  470. {
  471. VERBOSE(DBG_MSG,
  472. _T("Did not find '%s' keyword in ")
  473. _T("section '%s'. No action will be taken."),
  474. pszSearchKey,
  475. pszInstallSection);
  476. }
  477. }
  478. exit:
  479. return dwReturn;
  480. }
  481. /*++
  482. Routine description:
  483. Sets security info on a directory
  484. Arguments:
  485. lpszFolder [in] - name of directory
  486. lpszSD [in] - Desired security descriptor in SDDL format
  487. Return Value: Win32 Error code
  488. Written by: jobarner, 08/2002
  489. --*/
  490. DWORD SetDirSecurity(LPTSTR lpszFolder, LPCTSTR lpszSD)
  491. {
  492. PSECURITY_DESCRIPTOR pSD = NULL;
  493. DWORD ec = ERROR_SUCCESS;
  494. DBG_ENTER(_T("SetDirSecurity"),ec);
  495. if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
  496. lpszSD, SDDL_REVISION_1, &pSD, NULL))
  497. {
  498. ec = GetLastError();
  499. VERBOSE(SETUP_ERR, _T("ConvertStringSecurityDescriptorToSecurityDescriptor Failed, ec=%x"), ec);
  500. goto exit;
  501. }
  502. //
  503. // Apply the security descriptor recursively to the files.
  504. //
  505. BOOL bDaclPresent = TRUE;
  506. BOOL bDaclDefaulted = TRUE;
  507. PACL pDacl = NULL;
  508. if(!GetSecurityDescriptorDacl(pSD,
  509. &bDaclPresent,
  510. &pDacl,
  511. &bDaclDefaulted) ||
  512. !bDaclPresent)
  513. {
  514. ec = GetLastError();
  515. VERBOSE(SETUP_ERR, _T("GetSecurityDescriptorDacl Failed, ec=%x"), ec);
  516. goto exit;
  517. }
  518. ec = SetNamedSecurityInfo(lpszFolder,
  519. SE_FILE_OBJECT,
  520. DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
  521. NULL,
  522. NULL,
  523. pDacl,
  524. NULL);
  525. if (ec != ERROR_SUCCESS)
  526. {
  527. VERBOSE(SETUP_ERR, _T("SetSecurityInfo Failed, ec=%x"), ec);
  528. }
  529. exit:
  530. if (pSD)
  531. {
  532. LocalFree(pSD);
  533. }
  534. return ec;
  535. }
  536. /*++
  537. Routine description:
  538. Read dir name from registry and set security info on it
  539. Arguments:
  540. lpszKey [in] - name of subkey under HKLM
  541. lpszVal [in] - name of value that stores directory name
  542. lpszSD [in] - Desired security descriptor in SDDL format
  543. Return Value: Win32 Error code
  544. Written by: jobarner, 08/2002
  545. --*/
  546. DWORD SetDirSecurityFromReg(LPCTSTR lpszKey, LPCTSTR lpszVal, LPCTSTR lpszSD)
  547. {
  548. HKEY hKey = NULL;
  549. LPTSTR lpszFolder = NULL;
  550. DWORD ec = ERROR_SUCCESS;
  551. DBG_ENTER(_T("SetDirSecurityFromReg"),ec);
  552. hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, lpszKey, FALSE, KEY_READ);
  553. if (!hKey)
  554. {
  555. ec = GetLastError();
  556. VERBOSE(SETUP_ERR, _T("OpenRegistryKey Failed, ec=%x"), ec);
  557. goto exit;
  558. }
  559. lpszFolder = GetRegistryString(hKey, lpszVal, NULL);
  560. if (!lpszFolder)
  561. {
  562. ec = GetLastError();
  563. VERBOSE(SETUP_ERR, _T("GetRegistryString Failed, ec=%x"), ec);
  564. goto exit;
  565. }
  566. ec = SetDirSecurity(lpszFolder, lpszSD);
  567. exit:
  568. if (lpszFolder)
  569. {
  570. MemFree(lpszFolder);
  571. }
  572. if (hKey)
  573. {
  574. RegCloseKey(hKey);
  575. }
  576. return ec;
  577. }