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.

932 lines
25 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // STARTUP.CPP / Tuneup
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1998
  7. // All rights reserved
  8. //
  9. // Functions for the startup startmenu group wizard page.
  10. //
  11. // 7/98 - Jason Cohen (JCOHEN)
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. //
  15. // Include file(s).
  16. //
  17. #include "main.h"
  18. #include <shellapi.h>
  19. #include "startup.h"
  20. #include <lm.h>
  21. //
  22. // Internal defined values.
  23. //
  24. #define WM_REPLACEPROC WM_APP + 1
  25. //
  26. // Internal structure(s).
  27. //
  28. typedef struct _STARTUPLINK
  29. {
  30. BOOL bSelected;
  31. HICON hIcon;
  32. HICON hIconSelected;
  33. TCHAR szFileName[MAX_PATH];
  34. TCHAR szDisplayName[MAX_PATH];
  35. struct _STARTUPLINK *lpNext;
  36. } STARTUPLINK, *PSTARTUPLINK, *LPSTARTUPLINK;
  37. typedef struct _USERDIR
  38. {
  39. LPTSTR lpPath;
  40. LPSTARTUPLINK lpList;
  41. } USERDIR, *PUSERDIR, *LPUSERDIR;
  42. //
  43. // Internal global variable(s).
  44. //
  45. TCHAR g_szUserName[UNLEN + CNLEN + 1] = NULLSTR;
  46. LPSTARTUPLINK g_lpStartupLinks = NULL;
  47. //
  48. // Inernal function prototype(s).
  49. //
  50. static VOID FreeStartupLink(LPSTARTUPLINK, LPTSTR);
  51. static VOID InitStartupUsers(HWND);
  52. static BOOL CALLBACK AddString(HKEY, LPTSTR, LPARAM);
  53. static PSID GetUserSid(VOID);
  54. static LPTSTR GetSidString(PSID);
  55. static LRESULT CALLBACK ListBox_Proc(HWND, UINT, WPARAM, LPARAM);
  56. VOID InitStartupMenu(HWND hDlg)
  57. {
  58. PSID pSid = NULL;
  59. SID_NAME_USE SidName;
  60. TCHAR szKey[MAX_PATH + 1],
  61. szUserName[UNLEN],
  62. szCompName[CNLEN],
  63. szDomainName[DNLEN],
  64. szDisplayName[UNLEN + CNLEN + 1];
  65. DWORD cbUserName = sizeof(szUserName) / sizeof(TCHAR),
  66. cbCompName = sizeof(szCompName),
  67. cbDomainName = sizeof(szDomainName) / sizeof(TCHAR);
  68. INT nIndex = CB_ERR;
  69. LPTSTR lpBuffer;
  70. LPUSERDIR lpUserDir;
  71. LONG lMove;
  72. RECT ParentRect,
  73. Rect;
  74. // First things first, replace the list box windows procedure
  75. // so we can get the single click message.
  76. //
  77. ListBox_Proc(GetDlgItem(hDlg, IDC_STARTUP), WM_REPLACEPROC, 0, 0L);
  78. if ( IsUserAdmin() )
  79. {
  80. // Init the combo box.
  81. //
  82. InitStartupUsers(GetDlgItem(hDlg, IDC_USERS));
  83. }
  84. else
  85. {
  86. // Hide the combo box because user is not an administrator of
  87. // this machine.
  88. //
  89. ShowWindow(GetDlgItem(hDlg, IDC_SELUSER), FALSE);
  90. ShowWindow(GetDlgItem(hDlg, IDC_USERS), FALSE);
  91. // Now move the controls up so that they don't look out of place.
  92. //
  93. GetWindowRect(hDlg, &ParentRect);
  94. GetWindowRect(GetDlgItem(hDlg, IDC_SELUSER), &Rect);
  95. lMove = Rect.top;
  96. GetWindowRect(GetDlgItem(hDlg, IDC_PROGRAMS), &Rect);
  97. lMove -= Rect.top;
  98. SetWindowPos(GetDlgItem(hDlg, IDC_PROGRAMS), NULL, Rect.left - ParentRect.left, (Rect.top + lMove) - ParentRect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  99. GetWindowRect(GetDlgItem(hDlg, IDC_STARTUP), &Rect);
  100. SetWindowPos(GetDlgItem(hDlg, IDC_STARTUP), NULL, Rect.left - ParentRect.left, (Rect.top + lMove) - ParentRect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  101. // Lastly update the text box so that it make sence without the combo box.
  102. //
  103. if ( lpBuffer = AllocateString(NULL, IDS_STARTUPTEXT) )
  104. {
  105. SetDlgItemText(hDlg, IDC_STARTUPTEXT, lpBuffer);
  106. FREE(lpBuffer);
  107. }
  108. }
  109. if ( ( pSid = GetUserSid() ) &&
  110. ( lpBuffer = GetSidString(pSid) ) )
  111. {
  112. // First we need the profile directory for this user.
  113. //
  114. wsprintf(szKey, _T("%s\\%s"), g_szRegKeyProfiles, lpBuffer);
  115. FREE(lpBuffer);
  116. if ( lpBuffer = RegGetString(HKLM, szKey, _T("ProfileImagePath")) )
  117. {
  118. // We only want them if the directory exists.
  119. //
  120. if ( EXIST(lpBuffer) )
  121. {
  122. // Lookup the account info with the sid so we know the user and domain name.
  123. //
  124. if ( LookupAccountSid(NULL, pSid, szUserName, &cbUserName, szDomainName, &cbDomainName, &SidName) )
  125. {
  126. // Create the display name (combine the computer/domain name with the
  127. // user name unless the computer/domain name is the same as the computer name).
  128. //
  129. if ( ( GetComputerName(szCompName, &cbCompName) ) &&
  130. ( lstrcmp(szCompName, szDomainName) == 0 ) )
  131. lstrcpy(szDisplayName, szUserName);
  132. else
  133. wsprintf(szDisplayName, _T("%s\\%s"), szDomainName, szUserName);
  134. // Copy the display name to the global buffer.
  135. //
  136. lstrcpy(g_szUserName, szDisplayName);
  137. // Select the display name to the combo box.
  138. //
  139. if ( SendDlgItemMessage(hDlg, IDC_USERS, CB_SELECTSTRING, 0, (LPARAM) szDisplayName) == CB_ERR )
  140. {
  141. // It wasn't found, so we need to add it (probably because the user isn't and admin).
  142. //
  143. if ( (nIndex = (INT)SendDlgItemMessage(hDlg, IDC_USERS, CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) szDisplayName)) > CB_ERR )
  144. {
  145. if ( lpUserDir = (LPUSERDIR) MALLOC(sizeof(USERDIR)) )
  146. {
  147. lpUserDir->lpPath = lpBuffer;
  148. if ( (nIndex = (INT)SendDlgItemMessage(hDlg, IDC_USERS, CB_SETITEMDATA, nIndex, (LPARAM) lpUserDir)) == CB_ERR )
  149. FREE(lpUserDir);
  150. SendDlgItemMessage(hDlg, IDC_USERS, CB_SELECTSTRING, 0, (LPARAM) szDisplayName);
  151. }
  152. else
  153. {
  154. SendDlgItemMessage(hDlg, IDC_USERS, CB_DELETESTRING, nIndex, 0L);
  155. nIndex = CB_ERR;
  156. }
  157. }
  158. }
  159. // Now populate the startup groups.
  160. //
  161. InitStartupList(hDlg);
  162. }
  163. }
  164. // If we just added this string, don't free the buffer
  165. // that has the path to the profile.
  166. //
  167. if (nIndex < 0)
  168. FREE(lpBuffer);
  169. }
  170. }
  171. FREE(pSid);
  172. }
  173. VOID ReleaseStartupMenu(HWND hDlg)
  174. {
  175. INT nCount,
  176. nIndex;
  177. DWORD_PTR dwBuffer;
  178. LPUSERDIR lpUserDir;
  179. //
  180. // We need to free the buffer associated with each CB item.
  181. //
  182. // First get the count.
  183. //
  184. if ( (nCount = (INT)SendDlgItemMessage(hDlg, IDC_USERS, CB_GETCOUNT, 0, 0L)) > CB_ERR )
  185. {
  186. // Now go through all the items.
  187. //
  188. for (nIndex = 0; nIndex < nCount; nIndex++)
  189. {
  190. // Free the buffer stored in the CB item.
  191. //
  192. if ( (dwBuffer = SendDlgItemMessage(hDlg, IDC_USERS, CB_GETITEMDATA, nIndex, 0L)) != CB_ERR )
  193. {
  194. lpUserDir = (LPUSERDIR)dwBuffer;
  195. FreeStartupLink(lpUserDir->lpList, lpUserDir->lpPath);
  196. FREE(lpUserDir->lpPath);
  197. FREE(lpUserDir);
  198. }
  199. }
  200. }
  201. }
  202. BOOL InitStartupList(HWND hDlg)
  203. {
  204. INT iIndex,
  205. iString = IDS_STARTUP;
  206. DWORD_PTR dwBuffer;
  207. TCHAR szDir[MAX_PATH];
  208. LPUSERDIR lpUserDir;
  209. HANDLE hFindFile;
  210. WIN32_FIND_DATA FindData;
  211. SHFILEINFO SHFileInfo;
  212. LPSTARTUPLINK *lpNextLink = NULL;
  213. LPTSTR lpOffice95,
  214. lpOffice97;
  215. // First get the currently selected user from the combo box.
  216. //
  217. if ( ( (iIndex = (INT)SendDlgItemMessage(hDlg, IDC_USERS, CB_GETCURSEL, 0, 0L)) != CB_ERR ) &&
  218. ( (dwBuffer = SendDlgItemMessage(hDlg, IDC_USERS, CB_GETITEMDATA, iIndex, 0L)) != CB_ERR ) )
  219. {
  220. // Now remove all the current items from the list box.
  221. //
  222. SendDlgItemMessage(hDlg, IDC_STARTUP, LB_RESETCONTENT, 0, 0L);
  223. // Now get the profile directory stored as the extra data in the combo box.
  224. //
  225. lpUserDir = (LPUSERDIR)dwBuffer;
  226. // Check to see if we already have the files in this directory.
  227. //
  228. if ( lpUserDir->lpList )
  229. {
  230. // Add the names arleady found to the list box and set the structure pointer as the list box item data.
  231. //
  232. for (lpNextLink = &(lpUserDir->lpList); *lpNextLink; lpNextLink = &((*lpNextLink)->lpNext))
  233. if ( (iIndex = (INT)SendDlgItemMessage(hDlg, IDC_STARTUP, LB_ADDSTRING, 0, (LPARAM) (*lpNextLink)->szDisplayName)) >= 0 )
  234. SendDlgItemMessage(hDlg, IDC_STARTUP, LB_SETITEMDATA, iIndex, (LPARAM) *lpNextLink);
  235. }
  236. else
  237. {
  238. // Get the name of Office stuff which we want it default unchecked.
  239. //
  240. lpOffice95 = AllocateString(NULL, IDS_OFFICE95_STARTUP);
  241. lpOffice97 = AllocateString(NULL, IDS_OFFICE97_STARTUP);
  242. // Setup the pointer to the global structure that holds all the startup links.
  243. //
  244. lpNextLink = &lpUserDir->lpList;
  245. // Loop through the two directories (the actual startup items and the disabled ones).
  246. //
  247. while ( iString )
  248. {
  249. // Copy the profile path into the dir buffer.
  250. //
  251. lstrcpy(szDir, lpUserDir->lpPath);
  252. // Tack on the startup group to the end.
  253. //
  254. LoadString(NULL, iString, szDir + lstrlen(szDir), (sizeof(szDir) / sizeof(TCHAR)) - lstrlen(szDir) - 1);
  255. // Look for all the files.
  256. //
  257. if ( (hFindFile = FindFirstFile(szDir, &FindData)) != INVALID_HANDLE_VALUE )
  258. {
  259. do
  260. {
  261. // Ignore directories.
  262. //
  263. if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  264. {
  265. //
  266. // Ok, this is a link that we need to add. We need to build the
  267. // structure for it.
  268. //
  269. // Now allocate the memory we need for the structure that holds
  270. // all the info for the startup link.
  271. //
  272. if ( *lpNextLink = (LPSTARTUPLINK) MALLOC(sizeof(STARTUPLINK)) )
  273. {
  274. // Create the full path to the file and add it to the structure.
  275. //
  276. (*lpNextLink)->szFileName[0] = NULLCHR;
  277. lstrcpyn((*lpNextLink)->szFileName, szDir, lstrlen(szDir));
  278. lstrcat((*lpNextLink)->szFileName, FindData.cFileName);
  279. // Get the selected small icon for the file.
  280. //
  281. SHGetFileInfo((*lpNextLink)->szFileName, 0, &SHFileInfo, sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SELECTED);
  282. (*lpNextLink)->hIconSelected = SHFileInfo.hIcon;
  283. // Get the normal small icon and the display name
  284. // to use in the list box.
  285. //
  286. SHGetFileInfo((*lpNextLink)->szFileName, 0, &SHFileInfo, sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_DISPLAYNAME);
  287. (*lpNextLink)->hIcon = SHFileInfo.hIcon;
  288. lstrcpy((*lpNextLink)->szDisplayName, SHFileInfo.szDisplayName);
  289. // Set the initial selected state for the item.
  290. //
  291. if ( ( lstrcmpi(lpOffice95, (*lpNextLink)->szDisplayName) == 0 ) ||
  292. ( lstrcmpi(lpOffice97, (*lpNextLink)->szDisplayName) == 0 ) )
  293. (*lpNextLink)->bSelected = FALSE;
  294. else
  295. (*lpNextLink)->bSelected = ( iString == IDS_STARTUP );
  296. // Add the name to the list box and set the structure pointer as the list box item data.
  297. //
  298. if ( (iIndex = (INT)SendDlgItemMessage(hDlg, IDC_STARTUP, LB_ADDSTRING, 0, (LPARAM) SHFileInfo.szDisplayName)) >= 0 )
  299. {
  300. SendDlgItemMessage(hDlg, IDC_STARTUP, LB_SETITEMDATA, iIndex, (LPARAM) *lpNextLink);
  301. lpNextLink = &((*lpNextLink)->lpNext);
  302. }
  303. else
  304. FREE(*lpNextLink);
  305. }
  306. }
  307. }
  308. while ( FindNextFile(hFindFile, &FindData) );
  309. FindClose(hFindFile);
  310. }
  311. if ( iString == IDS_STARTUP )
  312. iString = IDS_APTUNEUP;
  313. else
  314. iString = 0;
  315. }
  316. }
  317. }
  318. return TRUE;
  319. }
  320. BOOL UserHasStartupItems()
  321. {
  322. PSID pSid;
  323. TCHAR szBuffer[MAX_PATH + 1];
  324. LPTSTR lpBuffer;
  325. BOOL bFound = FALSE;
  326. INT iString = IDS_STARTUP;
  327. HANDLE hFindFile;
  328. WIN32_FIND_DATA FindData;
  329. if ( ( pSid = GetUserSid() ) &&
  330. ( lpBuffer = GetSidString(pSid) ) )
  331. {
  332. // First we need the profile directory for this user.
  333. //
  334. wsprintf(szBuffer, _T("%s\\%s"), g_szRegKeyProfiles, lpBuffer);
  335. FREE(lpBuffer);
  336. // Get the users profile directory.
  337. //
  338. if ( lpBuffer = RegGetString(HKLM, szBuffer, _T("ProfileImagePath")) )
  339. {
  340. // We only want them if the directory exists.
  341. //
  342. if ( EXIST(lpBuffer) )
  343. {
  344. // Loop through the two directories (the actual startup items and the disabled ones).
  345. //
  346. while ( iString )
  347. {
  348. // Copy the user's profile directory into the buffer.
  349. //
  350. lstrcpy(szBuffer, lpBuffer);
  351. // Tack on the startup group to the end.
  352. //
  353. LoadString(NULL, iString, szBuffer + lstrlen(szBuffer), (sizeof(szBuffer) / sizeof(TCHAR)) - lstrlen(szBuffer) - 1);
  354. // Look for all the files.
  355. //
  356. if ( (hFindFile = FindFirstFile(szBuffer, &FindData)) != INVALID_HANDLE_VALUE )
  357. {
  358. do
  359. {
  360. // Ignore directories.
  361. //
  362. if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  363. bFound = TRUE;
  364. }
  365. while ( FindNextFile(hFindFile, &FindData) );
  366. FindClose(hFindFile);
  367. }
  368. if ( iString == IDS_STARTUP )
  369. iString = IDS_APTUNEUP;
  370. else
  371. iString = 0;
  372. }
  373. }
  374. FREE(lpBuffer);
  375. }
  376. }
  377. return bFound;
  378. }
  379. VOID SelectUserRadio(HWND hDlg, BOOL bAllNotCur)
  380. {
  381. LPTSTR lpBuffer;
  382. if (bAllNotCur)
  383. {
  384. if ( lpBuffer = AllocateString(NULL, IDS_ALLUSERS) )
  385. {
  386. SendDlgItemMessage(hDlg, IDC_USERS, CB_SELECTSTRING, 0, (LPARAM) lpBuffer);
  387. FREE(lpBuffer);
  388. }
  389. }
  390. else
  391. SendDlgItemMessage(hDlg, IDC_USERS, CB_SELECTSTRING, 0, (LPARAM) g_szUserName);
  392. InitStartupList(hDlg);
  393. }
  394. static VOID FreeStartupLink(LPSTARTUPLINK lpStartupLink, LPTSTR lpPath)
  395. {
  396. // Obviously don't want to free this memory if we were passed in NULL.
  397. //
  398. if ( lpStartupLink != NULL)
  399. {
  400. // Check to see if we need to move the file before
  401. // we free it's structure. We dynamically allocate the MAX_PATH
  402. // buffer so we don't fill up the stack with this recursive function.
  403. //
  404. if ( g_dwFlags & TUNEUP_FINISHED )
  405. {
  406. TCHAR szNewPath[MAX_PATH],
  407. szOldPath[MAX_PATH];
  408. LPTSTR lpOldName;
  409. // Copy the profile path into the dir buffer.
  410. //
  411. lstrcpy(szNewPath, lpPath);
  412. // Get the rest of the path info.
  413. //
  414. if ( lpStartupLink->bSelected )
  415. LoadString(NULL, IDS_STARTUP, szNewPath + lstrlen(szNewPath), (sizeof(szNewPath) / sizeof(TCHAR)) - lstrlen(szNewPath));
  416. else
  417. LoadString(NULL, IDS_APTUNEUP, szNewPath + lstrlen(szNewPath), (sizeof(szNewPath) / sizeof(TCHAR)) - lstrlen(szNewPath));
  418. // Remove the * from the end of the path.
  419. //
  420. *(szNewPath + lstrlen(szNewPath) - 1) = NULLCHR;
  421. // Make sure the path exists.
  422. //
  423. CreatePath(szNewPath);
  424. // Get a pointer to the file name.
  425. //
  426. GetFullPathName(lpStartupLink->szFileName, sizeof(szOldPath) / sizeof(TCHAR), szOldPath, &lpOldName);
  427. // Add the file name to the new path.
  428. //
  429. lstrcat(szNewPath, lpOldName);
  430. // Now we have the full path to what the file name should be.
  431. // If the file that should be there doesn't exist and the old
  432. // file name does, move it.
  433. //
  434. if ( !EXIST(szNewPath) && EXIST(szOldPath) )
  435. MoveFile(szOldPath, szNewPath);
  436. }
  437. // Free the next link.
  438. //
  439. FreeStartupLink(lpStartupLink->lpNext, lpPath);
  440. // Now finally free the memory for this link.
  441. //
  442. FREE(lpStartupLink);
  443. }
  444. }
  445. static VOID InitStartupUsers(HWND hCtrlUsers)
  446. {
  447. INT iString[] = { IDS_ALLUSERS, IDS_DEFAULTUSER, 0 },
  448. iId,
  449. iIndex;
  450. LPTSTR lpProfile,
  451. lpPath;
  452. LPUSERDIR lpUserDir;
  453. TCHAR szString[256];
  454. RegEnumKeys(HKLM, g_szRegKeyProfiles, (REGENUMKEYPROC) AddString, (LPARAM) hCtrlUsers, FALSE);
  455. if ( lpProfile = RegGetString(HKLM, g_szRegKeyProfiles, g_szRegValProfileDir) )
  456. {
  457. // Loop through the default users.
  458. //
  459. for (iId = 0; iString[iId] != 0; iId++)
  460. {
  461. // Load the string and allocate memory for it and the full path.
  462. //
  463. if ( ( LoadString(NULL, iString[iId], szString, sizeof(szString) / sizeof(TCHAR)) ) &&
  464. ( lpPath = (LPTSTR) MALLOC(sizeof(TCHAR) * (lstrlen(lpProfile) + lstrlen(szString) + 2)) ) )
  465. {
  466. // Create the full path.
  467. //
  468. wsprintf(lpPath, _T("%s\\%s"), lpProfile, szString);
  469. // Make sure the path exists.
  470. //
  471. if ( EXIST(lpPath) )
  472. {
  473. // Add the name to the combo box.
  474. //
  475. if ( (iIndex = (INT)SendMessage(hCtrlUsers, CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) szString)) > CB_ERR )
  476. {
  477. // Add the path data to the name.
  478. //
  479. if ( lpUserDir = (LPUSERDIR) MALLOC(sizeof(USERDIR)) )
  480. {
  481. lpUserDir->lpPath = lpPath;
  482. if ( (iIndex = (INT)SendMessage(hCtrlUsers, CB_SETITEMDATA, iIndex, (LPARAM) lpUserDir)) == CB_ERR )
  483. FREE(lpUserDir);
  484. }
  485. else
  486. {
  487. SendDlgItemMessage(hCtrlUsers, IDC_USERS, CB_DELETESTRING, iIndex, 0L);
  488. iIndex = CB_ERR;
  489. }
  490. }
  491. }
  492. else
  493. iIndex = CB_ERR;
  494. // If anything failed, we should free the buffer.
  495. //
  496. if ( iIndex <= CB_ERR )
  497. FREE(lpPath);
  498. }
  499. }
  500. // Free the path to the profiles.
  501. //
  502. FREE(lpProfile);
  503. }
  504. }
  505. static BOOL CALLBACK AddString(HKEY hKey, LPTSTR lpKey, LPARAM lParam)
  506. {
  507. LPTSTR lpBuffer;
  508. LPUSERDIR lpUserDir;
  509. PSID pSid;
  510. TCHAR szUserName[UNLEN],
  511. szCompName[CNLEN],
  512. szDomainName[DNLEN],
  513. szDisplayName[UNLEN + CNLEN + 1];
  514. DWORD cbUserName = sizeof(szUserName) / sizeof(TCHAR),
  515. cbCompName = sizeof(szCompName),
  516. cbDomainName = sizeof(szDomainName) / sizeof(TCHAR);
  517. INT nIndex = CB_ERR;
  518. SID_NAME_USE SidName;
  519. // First we need the profile directory for this user.
  520. //
  521. if ( lpBuffer = RegGetString(hKey, NULL, g_szRegValProfilePath) )
  522. {
  523. // We only want them if the directory exists.
  524. //
  525. if ( EXIST(lpBuffer) )
  526. {
  527. // Now get the sid for this user from the registry.
  528. //
  529. if ( pSid = (PSID) RegGetBin(hKey, NULL, _T("Sid")) )
  530. {
  531. // Lookup the account info with the sid so we know the user and domain name.
  532. //
  533. if ( LookupAccountSid(NULL, pSid, szUserName, &cbUserName, szDomainName, &cbDomainName, &SidName) )
  534. {
  535. // Create the display name (combine the computer/domain name with the
  536. // user name unless the computer/domain name is the same as the computer name.
  537. //
  538. if ( ( GetComputerName(szCompName, &cbCompName) ) &&
  539. ( lstrcmp(szCompName, szDomainName) == 0 ) )
  540. lstrcpy(szDisplayName, szUserName);
  541. else
  542. wsprintf(szDisplayName, _T("%s\\%s"), szDomainName, szUserName);
  543. // Add the display name to the combo box.
  544. //
  545. if ( (nIndex = (INT)SendMessage((HWND) lParam, CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) szDisplayName)) > CB_ERR )
  546. {
  547. if ( lpUserDir = (LPUSERDIR) MALLOC(sizeof(USERDIR)) )
  548. {
  549. lpUserDir->lpPath = lpBuffer;
  550. if ( (nIndex = (INT)SendMessage((HWND) lParam, CB_SETITEMDATA, nIndex, (LPARAM) lpUserDir)) == CB_ERR )
  551. FREE(lpUserDir);
  552. }
  553. else
  554. {
  555. SendDlgItemMessage((HWND) lParam, IDC_USERS, CB_DELETESTRING, nIndex, 0L);
  556. nIndex = CB_ERR;
  557. }
  558. }
  559. }
  560. FREE(pSid);
  561. }
  562. }
  563. // If the add never happend, we should free the buffer.
  564. //
  565. if (nIndex < 0)
  566. FREE(lpBuffer);
  567. }
  568. // Return TRUE to keep proccessing the registry keys.
  569. //
  570. return TRUE;
  571. }
  572. static PSID GetUserSid()
  573. {
  574. PTOKEN_USER pUser = NULL;
  575. DWORD dwSize = 0;
  576. HANDLE hToken = INVALID_HANDLE_VALUE;
  577. PSID pSid = NULL;
  578. // Get the current process token and
  579. // allocate space for and get the user info.
  580. //
  581. if ( !( ( OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ) &&
  582. ( !GetTokenInformation(hToken, TokenUser, pUser, dwSize, &dwSize) ) &&
  583. ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) &&
  584. ( pUser = (PTOKEN_USER) MALLOC(dwSize) ) &&
  585. ( GetTokenInformation(hToken, TokenUser, pUser, dwSize, &dwSize) ) &&
  586. ( pSid = (PSID) MALLOC(dwSize = GetLengthSid(pUser->User.Sid)) ) &&
  587. ( CopySid(dwSize, pSid, pUser->User.Sid) ) ) )
  588. // If all those items didn't succeed, we need to free the sid.
  589. // This macro automatically checks for NULL before freeing and
  590. // sets to NULL after freeing.
  591. //
  592. FREE(pSid);
  593. // Free up and close up the resources used.
  594. //
  595. FREE(pUser);
  596. if ( hToken != INVALID_HANDLE_VALUE )
  597. CloseHandle(hToken);
  598. return pSid;
  599. }
  600. static LPTSTR GetSidString(PSID pSid)
  601. {
  602. LPTSTR lpszSid = NULL;
  603. PSID_IDENTIFIER_AUTHORITY pSidIA;
  604. DWORD dwSubAuthorities,
  605. dwCounter,
  606. dwSidSize;
  607. // Check to make sure the Sid is vallid.
  608. //
  609. if ( pSid && IsValidSid(pSid) )
  610. {
  611. // Obtain SidIdentifierAuthority
  612. //
  613. pSidIA = GetSidIdentifierAuthority(pSid);
  614. // Obtain SidSubAuthority count
  615. //
  616. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  617. // Compute buffer length:
  618. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  619. //
  620. dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  621. // Automatically allocate the space needed for the Sid.
  622. //
  623. if ( lpszSid = (LPTSTR) MALLOC(dwSidSize) )
  624. {
  625. // Prepare S-SID_REVISION-
  626. //
  627. dwSidSize = wsprintf(lpszSid, TEXT("S-%lu-"), SID_REVISION);
  628. // Prepare SidIdentifierAuthority.
  629. //
  630. if ( ( pSidIA->Value[0] != 0 ) || ( pSidIA->Value[1] != 0 ) )
  631. {
  632. dwSidSize += wsprintf(
  633. lpszSid + lstrlen(lpszSid),
  634. _T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  635. (USHORT) pSidIA->Value[0],
  636. (USHORT) pSidIA->Value[1],
  637. (USHORT) pSidIA->Value[2],
  638. (USHORT) pSidIA->Value[3],
  639. (USHORT) pSidIA->Value[4],
  640. (USHORT) pSidIA->Value[5]
  641. );
  642. }
  643. else
  644. {
  645. dwSidSize += wsprintf(lpszSid + lstrlen(lpszSid),
  646. _T("%lu"),
  647. (ULONG) (pSidIA->Value[5] ) +
  648. (ULONG) (pSidIA->Value[4] << 8) +
  649. (ULONG) (pSidIA->Value[3] << 16) +
  650. (ULONG) (pSidIA->Value[2] << 24)
  651. );
  652. }
  653. // Loop through SidSubAuthorities.
  654. //
  655. for (dwCounter = 0; dwCounter < dwSubAuthorities; dwCounter++)
  656. dwSidSize += wsprintf(lpszSid + dwSidSize, _T("-%lu"), *GetSidSubAuthority(pSid, dwCounter));
  657. }
  658. }
  659. return lpszSid;
  660. }
  661. BOOL StartupDrawItem(HWND hWnd, const DRAWITEMSTRUCT * lpDrawItem)
  662. {
  663. TCHAR szBuffer[MAX_PATH];
  664. BOOL bRestore = FALSE;
  665. COLORREF crText,
  666. crBk;
  667. DWORD dwColor;
  668. RECT rect;
  669. HBRUSH hbrBack;
  670. LPSTARTUPLINK lpStartupLink;
  671. static HICON hIconCheck = NULL,
  672. hIconUnCheck = NULL;
  673. switch ( lpDrawItem->itemAction )
  674. {
  675. case ODA_SELECT:
  676. case ODA_DRAWENTIRE:
  677. if (lpDrawItem->itemState & ODS_SELECTED)
  678. {
  679. // Set new text/background colors and store the old ones away.
  680. //
  681. crText = SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  682. crBk = SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHT));
  683. // Restore the text and background colors when we are finished.
  684. //
  685. bRestore = TRUE;
  686. // Get the hightlight color to fill in the listbox item.
  687. //
  688. dwColor = GetSysColor(COLOR_HIGHLIGHT);
  689. }
  690. else
  691. {
  692. // Get the window color so we can clear the listbox item.
  693. //
  694. dwColor = GetSysColor(COLOR_WINDOW);
  695. }
  696. // Fill entire item rectangle with the appropriate color
  697. //
  698. hbrBack = CreateSolidBrush(dwColor);
  699. FillRect(lpDrawItem->hDC, &(lpDrawItem->rcItem), hbrBack);
  700. DeleteObject(hbrBack);
  701. // Display the icon associated with the item.
  702. //
  703. if ( lpStartupLink = (LPSTARTUPLINK) SendMessage(lpDrawItem->hwndItem, LB_GETITEMDATA, lpDrawItem->itemID, (LPARAM) 0) )
  704. {
  705. // Load the checked and unchecked icons if we don't
  706. // have them already.
  707. //
  708. if ( hIconCheck == NULL )
  709. hIconCheck = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_CHECK), IMAGE_ICON, 16, 16, 0);
  710. if ( hIconUnCheck == NULL )
  711. hIconUnCheck = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_UNCHECK), IMAGE_ICON, 16, 16, 0);
  712. // Draw the checked or unchecked icon.
  713. //
  714. DrawIconEx( lpDrawItem->hDC,
  715. lpDrawItem->rcItem.left,
  716. lpDrawItem->rcItem.top,
  717. lpStartupLink->bSelected ? hIconCheck : hIconUnCheck,
  718. lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
  719. lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
  720. 0,
  721. 0,
  722. DI_NORMAL);
  723. // Draw the items icon.
  724. //
  725. DrawIconEx( lpDrawItem->hDC,
  726. lpDrawItem->rcItem.left + lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top + 2,
  727. lpDrawItem->rcItem.top,
  728. (lpDrawItem->itemState & ODS_SELECTED) ? lpStartupLink->hIconSelected : lpStartupLink->hIcon,
  729. lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
  730. lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
  731. 0,
  732. 0,
  733. DI_NORMAL);
  734. }
  735. // Display the text associated with the item.
  736. //
  737. SendMessage(lpDrawItem->hwndItem, LB_GETTEXT, lpDrawItem->itemID, (LPARAM) szBuffer);
  738. TextOut( lpDrawItem->hDC,
  739. lpDrawItem->rcItem.left + ((lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top + 2) * 2),
  740. lpDrawItem->rcItem.top + 1,
  741. szBuffer,
  742. lstrlen(szBuffer));
  743. if (bRestore)
  744. {
  745. // Restore original text and background colors.
  746. //
  747. SetTextColor(lpDrawItem->hDC, crText);
  748. SetBkColor(lpDrawItem->hDC, crBk);
  749. }
  750. break;
  751. case ODA_FOCUS:
  752. // Get rectangle coordinates for listbox item.
  753. //
  754. SendMessage(lpDrawItem->hwndItem, LB_GETITEMRECT, lpDrawItem->itemID, (LPARAM) &rect);
  755. DrawFocusRect(lpDrawItem->hDC, &rect);
  756. break;
  757. }
  758. return TRUE;
  759. }
  760. VOID StartupSelectItem(HWND hWndCtrl)
  761. {
  762. INT nIndex;
  763. LPSTARTUPLINK lpStartupLink;
  764. if ( ( (nIndex = (INT)SendMessage(hWndCtrl, LB_GETCURSEL, 0, 0L)) >= 0 ) &&
  765. ( (lpStartupLink = (LPSTARTUPLINK) SendMessage(hWndCtrl, LB_GETITEMDATA, nIndex, 0L)) != NULL ) )
  766. {
  767. lpStartupLink->bSelected = !lpStartupLink->bSelected;
  768. SendMessage(hWndCtrl, LB_SETCURSEL, (WPARAM) nIndex, 0L);
  769. }
  770. }
  771. static LRESULT CALLBACK ListBox_Proc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  772. {
  773. static WNDPROC ListBoxProc = NULL;
  774. LONG rc = 0;
  775. if ( iMsg == WM_REPLACEPROC )
  776. {
  777. // Replace the default Windows procedure for the list box. AKA: The Glorious Hack!
  778. //
  779. if ( ( ListBoxProc == NULL ) &&
  780. ( (ListBoxProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_WNDPROC)) != NULL ) )
  781. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR) ListBox_Proc);
  782. return rc;
  783. }
  784. // Just a safty catch to make sure we have the default windows procedure.
  785. //
  786. if ( ( ListBoxProc == NULL ) &&
  787. ( (ListBoxProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_WNDPROC)) == NULL ) )
  788. return rc;
  789. // Let the standard window proc handle the message.
  790. //
  791. rc = (LONG)CallWindowProc((WNDPROC) ListBoxProc, hWnd, iMsg, wParam, lParam);
  792. // Do the single click thing if we need to.
  793. //
  794. if ( ( iMsg == WM_LBUTTONDOWN ) &&
  795. ( (LOWORD(lParam) < 16) && (HIWORD(lParam) < (SendMessage(hWnd, LB_GETCOUNT, 0, 0L) * 16)) ) )
  796. StartupSelectItem(hWnd);
  797. return rc;
  798. }