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.

1089 lines
25 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1999 **
  4. //*********************************************************************
  5. //
  6. // UTIL.CPP - utilities
  7. //
  8. // HISTORY:
  9. //
  10. // 1/27/99 a-jaswed Created.
  11. //
  12. // Common utilities for printing out messages
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <objbase.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <stdarg.h>
  20. #include "util.h"
  21. #include "appdefs.h"
  22. #include <shlwapi.h>
  23. #include <shlobj.h>
  24. #include <shfolder.h>
  25. #include <wchar.h>
  26. #include <winsvcp.h> // for SC_OOBE_MACHINE_NAME_DONE
  27. #include <safeboot.h> // for SAFEBOOT_DSREPAIR_STR_W
  28. ///////////////////////////////////////////////////////////
  29. // Print out the COM/OLE error string for an HRESULT.
  30. //
  31. void ErrorMessage(LPCWSTR message, HRESULT hr)
  32. {
  33. const WCHAR* sz ;
  34. if (message == NULL)
  35. {
  36. sz = L"The following error occured." ;
  37. }
  38. else
  39. {
  40. sz = message ;
  41. }
  42. void* pMsgBuf;
  43. ::FormatMessage(
  44. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  45. NULL,
  46. hr,
  47. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  48. (LPWSTR) &pMsgBuf,
  49. 0,
  50. NULL
  51. );
  52. WCHAR buf[256] ;
  53. wsprintf(buf, L"%s\r\nError: (%x) - %s", sz, hr, (LPWSTR)pMsgBuf) ;
  54. MessageBox(NULL, buf, L"Utility Error Message Box.", MB_OK) ;
  55. // Free the buffer.
  56. LocalFree( pMsgBuf );
  57. }
  58. ////////////////////////////////////////////////////////////
  59. // Check to see if both interfaces are on the same component.
  60. //
  61. BOOL InterfacesAreOnSameComponent(IUnknown* p1, IUnknown* p2)
  62. {
  63. HRESULT hr = S_OK ;
  64. // Get the real IUnknown for the first interface.
  65. IUnknown* pReal1 = NULL ;
  66. hr = p1->QueryInterface(IID_IUnknown, (void**)&pReal1) ;
  67. assert(SUCCEEDED(hr)) ;
  68. // Get the real IUnknown for the second interface.
  69. IUnknown* pReal2 = NULL ;
  70. hr = p2->QueryInterface(IID_IUnknown, (void**)&pReal2) ;
  71. assert(SUCCEEDED(hr)) ;
  72. // Compare the IUnknown pointers.
  73. BOOL bReturn = (pReal1 == pReal2) ;
  74. // Cleanup
  75. pReal1->Release() ;
  76. pReal2->Release() ;
  77. // Return the value.
  78. return bReturn;
  79. }
  80. ///////////////////////////////////////////////////////////
  81. // IsValidAddress
  82. //
  83. BOOL IsValidAddress(const void* lp, UINT nBytes, BOOL bReadWrite)
  84. {
  85. return (lp != NULL && !::IsBadReadPtr(lp, nBytes) &&
  86. (!bReadWrite || !::IsBadWritePtr((LPVOID)lp, nBytes)));
  87. }
  88. ///////////////////////////////////////////////////////////
  89. // MyDebug
  90. //
  91. #if ASSERTS_ON
  92. VOID
  93. AssertFail(
  94. IN PSTR FileName,
  95. IN UINT LineNumber,
  96. IN PSTR Condition
  97. )
  98. {
  99. int i;
  100. CHAR Name[MAX_PATH];
  101. PCHAR p;
  102. CHAR Msg[4096];
  103. //
  104. // Use dll name as caption
  105. //
  106. GetModuleFileNameA(NULL,Name,MAX_PATH);
  107. if(p = strrchr(Name,'\\')) {
  108. p++;
  109. } else {
  110. p = Name;
  111. }
  112. wsprintfA(
  113. Msg,
  114. "Assertion failure at line %u in file %s: %s%s",
  115. LineNumber,
  116. FileName,
  117. Condition,
  118. "\n\nCall DebugBreak()?"
  119. );
  120. i = MessageBoxA(
  121. NULL,
  122. Msg,
  123. p,
  124. MB_YESNO | MB_TASKMODAL | MB_ICONSTOP | MB_SETFOREGROUND
  125. );
  126. if(i == IDYES) {
  127. DebugBreak();
  128. }
  129. }
  130. #endif
  131. ///////////////////////////////////////////////////////////
  132. // Trace
  133. //
  134. void __cdecl MyTrace(LPCWSTR lpszFormat, ...)
  135. {
  136. USES_CONVERSION;
  137. va_list args;
  138. va_start(args, lpszFormat);
  139. int nBuf;
  140. WCHAR szBuffer[512];
  141. nBuf = _vsnwprintf(szBuffer, MAX_CHARS_IN_BUFFER(szBuffer), lpszFormat, args);
  142. // was there an error? was the expanded string too long?
  143. assert(nBuf > 0);
  144. #if DBG
  145. DbgPrintEx( DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, W2A(szBuffer) );
  146. #endif
  147. va_end(args);
  148. }
  149. //BUGBUG need bettter default
  150. bool GetString(HINSTANCE hInstance, UINT uiID, LPWSTR szString, UINT uiStringLen)
  151. {
  152. // BUGBUG: Should this assume current module if hInstance is NULL??
  153. MYASSERT(NULL != hInstance);
  154. if (NULL != hInstance)
  155. return (0 < LoadString(hInstance, uiID, szString, uiStringLen));
  156. else
  157. return (false);
  158. }
  159. // the goal of this function is to be able to able to get to
  160. // c:\windows dir\system dir\oobe\oobeinfo.ini
  161. // c:\windows dir\system dir\oeminfo.ini
  162. // c:\windows dir\oemaudit.oem
  163. // the canonicalize allows the specification for oemaudit.oem to be ..\oemaudit.oem
  164. bool GetCanonicalizedPath(LPWSTR szCompletePath, LPCWSTR szFileName)
  165. {
  166. if (0 < GetSystemDirectory(szCompletePath, MAX_PATH))
  167. {
  168. lstrcat(szCompletePath, szFileName);
  169. WCHAR szLocal[MAX_PATH];
  170. lstrcpy(szLocal, szCompletePath);
  171. return PathCanonicalize(szCompletePath, (LPCWSTR) szLocal) ? true : false;
  172. }
  173. return false;
  174. }
  175. bool GetOOBEPath(LPWSTR szOOBEPath)
  176. {
  177. if (0 < GetSystemDirectory(szOOBEPath, MAX_PATH))
  178. {
  179. lstrcat(szOOBEPath, L"\\OOBE");
  180. return true;
  181. }
  182. return false;
  183. }
  184. // This returns the path for the localized OOBE files on a system with MUI.
  185. //
  186. bool GetOOBEMUIPath(LPWSTR szOOBEPath)
  187. {
  188. LANGID UILang;
  189. WCHAR szMUIPath[MAX_PATH];
  190. if (GetOOBEPath(szOOBEPath))
  191. {
  192. UILang = GetUserDefaultUILanguage();
  193. if ( UILang != GetSystemDefaultUILanguage() ) {
  194. wsprintf( szMUIPath, L"\\MUI\\%04x", UILang );
  195. lstrcat(szOOBEPath, szMUIPath );
  196. }
  197. return true;
  198. }
  199. return false;
  200. }
  201. HRESULT GetINIKey(HINSTANCE hInstance, LPCWSTR szINIFileName, UINT uiSectionName, UINT uiKeyName, LPVARIANT pvResult)
  202. {
  203. WCHAR szSectionName[MAX_PATH], szKeyName[MAX_PATH];
  204. WCHAR szItem[1024]; //bugbug bad constant
  205. if (GetString(hInstance, uiSectionName, szSectionName) && GetString(hInstance, uiKeyName, szKeyName))
  206. {
  207. WCHAR szINIPath[MAX_PATH];
  208. if (GetCanonicalizedPath(szINIPath, szINIFileName))
  209. {
  210. if (VT_I4 == V_VT(pvResult))
  211. {
  212. V_I4(pvResult) = GetPrivateProfileInt(szSectionName, szKeyName, 0, szINIPath);
  213. return S_OK;
  214. }
  215. else
  216. {
  217. if (GetPrivateProfileString(
  218. szSectionName,
  219. szKeyName,
  220. L"",
  221. szItem,
  222. MAX_CHARS_IN_BUFFER(szItem),
  223. szINIPath))
  224. {
  225. V_BSTR(pvResult) = SysAllocString(szItem);
  226. return S_OK;
  227. }
  228. }
  229. }
  230. }
  231. if (VT_BSTR == V_VT(pvResult))
  232. V_BSTR(pvResult) = SysAllocString(L"\0");
  233. else
  234. V_I4(pvResult) = 0;
  235. return S_OK;
  236. }
  237. HRESULT GetINIKeyBSTR(HINSTANCE hInstance, LPCWSTR szINIFileName, UINT uiSectionName, UINT uiKeyName, LPVARIANT pvResult)
  238. {
  239. VariantInit(pvResult);
  240. V_VT(pvResult) = VT_BSTR;
  241. return (GetINIKey(hInstance, szINIFileName, uiSectionName, uiKeyName, pvResult));
  242. }
  243. HRESULT GetINIKeyUINT(HINSTANCE hInstance, LPCWSTR szINIFileName, UINT uiSectionName, UINT uiKeyName, LPVARIANT pvResult)
  244. {
  245. VariantInit(pvResult);
  246. V_VT(pvResult) = VT_I4;
  247. return (GetINIKey(hInstance, szINIFileName, uiSectionName, uiKeyName, pvResult));
  248. }
  249. HRESULT SetINIKey(HINSTANCE hInstance, LPCWSTR szINIFileName, UINT uiSectionName, UINT uiKeyName, LPVARIANT pvResult)
  250. {
  251. WCHAR szSectionName[MAX_PATH], szKeyName[MAX_PATH];
  252. VariantInit(pvResult);
  253. V_VT(pvResult) = VT_BSTR;
  254. if (GetString(hInstance, uiSectionName, szSectionName) && GetString(hInstance, uiKeyName, szKeyName))
  255. {
  256. if (WritePrivateProfileString(V_BSTR(pvResult), szKeyName,
  257. V_BSTR(pvResult), szINIFileName))
  258. {
  259. return S_OK;
  260. }
  261. }
  262. return E_FAIL;
  263. }
  264. void WINAPI URLEncode(WCHAR* pszUrl, size_t bsize)
  265. {
  266. if (!pszUrl)
  267. return;
  268. WCHAR* pszEncode = NULL;
  269. WCHAR* pszEStart = NULL;
  270. WCHAR* pszEEnd = (WCHAR*)wmemchr( pszUrl, L'\0', bsize );
  271. int iUrlLen = (int)(pszEEnd-pszUrl);
  272. pszEEnd = pszUrl;
  273. WCHAR c;
  274. size_t cch = (iUrlLen+1) * sizeof(WCHAR) * 3;
  275. assert( cch <= bsize );
  276. if (cch <= bsize)
  277. {
  278. pszEncode = (WCHAR*)malloc(BYTES_REQUIRED_BY_CCH(cch));
  279. if(pszEncode)
  280. {
  281. pszEStart = pszEncode;
  282. ZeroMemory(pszEncode, BYTES_REQUIRED_BY_CCH(cch));
  283. for(; c = *(pszUrl); pszUrl++)
  284. {
  285. switch(c)
  286. {
  287. case L' ': //SPACE
  288. memcpy(pszEncode, L"+", 1*sizeof(WCHAR));
  289. pszEncode+=1;
  290. break;
  291. case L'#':
  292. memcpy(pszEncode, L"%23", 3*sizeof(WCHAR));
  293. pszEncode+=3;
  294. break;
  295. case L'&':
  296. memcpy(pszEncode, L"%26", 3*sizeof(WCHAR));
  297. pszEncode+=3;
  298. break;
  299. case L'%':
  300. memcpy(pszEncode, L"%25", 3*sizeof(WCHAR));
  301. pszEncode+=3;
  302. break;
  303. case L'=':
  304. memcpy(pszEncode, L"%3D", 3*sizeof(WCHAR));
  305. pszEncode+=3;
  306. break;
  307. case L'<':
  308. memcpy(pszEncode, L"%3C", 3*sizeof(WCHAR));
  309. pszEncode+=3;
  310. break;
  311. case L'+':
  312. memcpy(pszEncode, L"%2B", 3*sizeof(WCHAR));
  313. pszEncode += 3;
  314. break;
  315. default:
  316. *pszEncode++ = c;
  317. break;
  318. }
  319. }
  320. *pszEncode++ = L'\0';
  321. memcpy(pszEEnd ,pszEStart, (size_t)(pszEncode - pszEStart));
  322. free(pszEStart);
  323. }
  324. }
  325. }
  326. //BUGBUG: Need to turn spaces into "+"
  327. void WINAPI URLAppendQueryPair
  328. (
  329. LPWSTR lpszQuery,
  330. LPWSTR lpszName,
  331. LPWSTR lpszValue OPTIONAL
  332. )
  333. {
  334. // Append the Name
  335. lstrcat(lpszQuery, lpszName);
  336. lstrcat(lpszQuery, cszEquals);
  337. // Append the Value
  338. if ( lpszValue ) {
  339. lstrcat(lpszQuery, lpszValue);
  340. }
  341. // Append an Ampersand if this is NOT the last pair
  342. lstrcat(lpszQuery, cszAmpersand);
  343. }
  344. void GetCmdLineToken(LPWSTR *ppszCmd, LPWSTR pszOut)
  345. {
  346. LPWSTR c;
  347. int i = 0;
  348. BOOL fInQuote = FALSE;
  349. c = *ppszCmd;
  350. pszOut[0] = *c;
  351. if (!*c)
  352. return;
  353. if (*c == L' ')
  354. {
  355. pszOut[1] = L'\0';
  356. *ppszCmd = c+1;
  357. return;
  358. }
  359. else if( L'"' == *c )
  360. {
  361. fInQuote = TRUE;
  362. }
  363. NextChar:
  364. i++;
  365. c++;
  366. if( !*c || (!fInQuote && (*c == L' ')) )
  367. {
  368. pszOut[i] = L'\0';
  369. *ppszCmd = c;
  370. return;
  371. }
  372. else if( fInQuote && (*c == L'"') )
  373. {
  374. fInQuote = FALSE;
  375. pszOut[i] = *c;
  376. i++;
  377. c++;
  378. pszOut[i] = L'\0';
  379. *ppszCmd = c;
  380. return;
  381. }
  382. else
  383. {
  384. pszOut[i] = *c;
  385. goto NextChar;
  386. }
  387. }
  388. BOOL IsOEMDebugMode()
  389. {
  390. HKEY hKey = NULL;
  391. DWORD dwIsDebug = 0;
  392. DWORD dwSize = sizeof(dwIsDebug);
  393. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  394. OOBE_MAIN_REG_KEY,
  395. 0,
  396. KEY_QUERY_VALUE,
  397. &hKey) == ERROR_SUCCESS)
  398. {
  399. RegQueryValueEx(hKey,
  400. OOBE_OEMDEBUG_REG_VAL,
  401. 0,
  402. NULL,
  403. (LPBYTE)&dwIsDebug,
  404. &dwSize);
  405. RegCloseKey(hKey);
  406. }
  407. #ifdef DEBUG
  408. return (BOOL)1;
  409. #else
  410. return (BOOL)dwIsDebug;
  411. #endif
  412. }
  413. VOID
  414. PumpMessageQueue(
  415. VOID
  416. )
  417. {
  418. MSG msg;
  419. while(PeekMessage(&msg, NULL, 0,0,PM_REMOVE)) {
  420. DispatchMessage(&msg);
  421. }
  422. }
  423. BOOL
  424. IsThreadActive(
  425. HANDLE hThread
  426. )
  427. {
  428. DWORD dwExitCode = 0;
  429. return (NULL != hThread
  430. && GetExitCodeThread(hThread, &dwExitCode)
  431. && STILL_ACTIVE == dwExitCode
  432. );
  433. }
  434. void GetDesktopDirectory(WCHAR* pszPath)
  435. {
  436. WCHAR pszFolder[MAX_PATH];
  437. *pszFolder = L'\0';
  438. HRESULT hRet = SHGetFolderPath(NULL, CSIDL_COMMON_DESKTOPDIRECTORY,
  439. NULL, 0, pszFolder
  440. );
  441. if (S_OK != hRet)
  442. {
  443. hRet = SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY,
  444. NULL, 0, pszFolder
  445. );
  446. }
  447. if (S_OK == hRet)
  448. {
  449. lstrcpy(pszPath , pszFolder);
  450. }
  451. }
  452. void RemoveDesktopShortCut
  453. (
  454. LPWSTR lpszShortcutName
  455. )
  456. {
  457. WCHAR szShortcutPath[MAX_PATH] = L"\0";
  458. GetDesktopDirectory(szShortcutPath);
  459. if(szShortcutPath[0] != L'\0')
  460. {
  461. lstrcat(szShortcutPath, L"\\");
  462. lstrcat(szShortcutPath, lpszShortcutName);
  463. lstrcat(szShortcutPath, L".LNK");
  464. DeleteFile(szShortcutPath);
  465. }
  466. }
  467. BOOL
  468. InvokeExternalApplication(
  469. IN PCWSTR ApplicationName, OPTIONAL
  470. IN PCWSTR CommandLine,
  471. IN OUT PDWORD ExitCode OPTIONAL
  472. )
  473. /*++
  474. Routine Description:
  475. Invokes an external program, which is optionally detached.
  476. Arguments:
  477. ApplicationName - supplies app name. May be a partial or full path,
  478. or just a filename, in which case the standard win32 path search
  479. is performed. If not specified then the first element in
  480. CommandLine must specify the binary to execute.
  481. CommandLine - supplies the command line to be passed to the
  482. application.
  483. ExitCode - If specified, the execution is synchronous and this value
  484. receives the exit code of the application. If not specified,
  485. the execution is asynchronous.
  486. Return Value:
  487. Boolean value indicating whether the process was started successfully.
  488. --*/
  489. {
  490. PWSTR FullCommandLine;
  491. BOOL b;
  492. PROCESS_INFORMATION ProcessInfo;
  493. STARTUPINFO StartupInfo;
  494. DWORD d;
  495. b = FALSE;
  496. //
  497. // Form the command line to be passed to CreateProcess.
  498. //
  499. if(ApplicationName) {
  500. FullCommandLine =
  501. (PWSTR) malloc(BYTES_REQUIRED_BY_SZ(ApplicationName)+BYTES_REQUIRED_BY_SZ(CommandLine)+BYTES_REQUIRED_BY_CCH(2));
  502. if(!FullCommandLine) {
  503. goto err0;
  504. }
  505. lstrcpy(FullCommandLine, ApplicationName);
  506. lstrcat(FullCommandLine, L" ");
  507. lstrcat(FullCommandLine, CommandLine);
  508. } else {
  509. FullCommandLine =
  510. (PWSTR) malloc(BYTES_REQUIRED_BY_SZ(CommandLine));
  511. if(!FullCommandLine) {
  512. goto err0;
  513. }
  514. lstrcpy(FullCommandLine, CommandLine);
  515. }
  516. //
  517. // Initialize startup info.
  518. //
  519. ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
  520. StartupInfo.cb = sizeof(STARTUPINFO);
  521. //
  522. // Create the process.
  523. //
  524. b = CreateProcess(
  525. NULL,
  526. FullCommandLine,
  527. NULL,
  528. NULL,
  529. FALSE,
  530. ExitCode ? 0 : DETACHED_PROCESS,
  531. NULL,
  532. NULL,
  533. &StartupInfo,
  534. &ProcessInfo
  535. );
  536. if(!b) {
  537. goto err1;
  538. }
  539. //
  540. // If execution is asynchronus, we're done.
  541. //
  542. if(!ExitCode) {
  543. goto err2;
  544. }
  545. err2:
  546. CloseHandle(ProcessInfo.hThread);
  547. CloseHandle(ProcessInfo.hProcess);
  548. err1:
  549. free(FullCommandLine);
  550. err0:
  551. return(b);
  552. }
  553. //////////////////////////////////////////////////////////////////////////////
  554. //
  555. // InSafeMode
  556. //
  557. // Determine whether the system is running in safe mode or clean mode.
  558. //
  559. // parameters:
  560. // None.
  561. //
  562. // returns:
  563. // TRUE if the system was booted in safe mode
  564. // FALSE if the system was booted in clean mode
  565. //
  566. //////////////////////////////////////////////////////////////////////////////
  567. BOOL
  568. InSafeMode()
  569. {
  570. if (BOOT_CLEAN != GetSystemMetrics(SM_CLEANBOOT))
  571. {
  572. TRACE(L"Running in SAFEMODE...");
  573. return TRUE;
  574. }
  575. return FALSE;
  576. } // InSafeMode
  577. //////////////////////////////////////////////////////////////////////////////
  578. //
  579. // InDsRestoreMode
  580. //
  581. // Determine whether the system is running in Directory Services Restore Mode
  582. //
  583. // parameters:
  584. // None.
  585. //
  586. // returns:
  587. // TRUE if the system was booted in restore mode
  588. // FALSE if the system was not booted in restore mode
  589. //
  590. //////////////////////////////////////////////////////////////////////////////
  591. BOOL
  592. InDsRestoreMode()
  593. {
  594. WCHAR SafeBootEnvVar[ARRAYSIZE(SAFEBOOT_DSREPAIR_STR_W)] = L"\0";
  595. if ( GetEnvironmentVariableW( L"SAFEBOOT_OPTION",
  596. SafeBootEnvVar,
  597. ARRAYSIZE(SafeBootEnvVar) ) )
  598. {
  599. if ( wcscmp( SafeBootEnvVar, SAFEBOOT_DSREPAIR_STR_W ) == 0 )
  600. {
  601. TRACE(L"Running in DS Restore Mode...");
  602. return TRUE;
  603. }
  604. }
  605. return FALSE;
  606. } // InDsRestoreMode
  607. // Signal winlogon that the computer name has been changed. WinLogon waits to
  608. // start services that depend on the computer name until this event is
  609. // signalled.
  610. //
  611. BOOL
  612. SignalComputerNameChangeComplete()
  613. {
  614. BOOL fReturn = TRUE;
  615. // Open event with EVENT_ALL_ACCESS so that synchronization and state
  616. // change can be done.
  617. //
  618. HANDLE hevent = OpenEvent(EVENT_ALL_ACCESS,
  619. FALSE,
  620. SC_OOBE_MACHINE_NAME_DONE
  621. );
  622. // It is not fatal for OpenEvent to fail: this synchronization is only
  623. // required when OOBE will be run in OEM mode.
  624. //
  625. if (NULL != hevent)
  626. {
  627. if (! SetEvent(hevent))
  628. {
  629. // It is fatal to open but not set the event: services.exe will not
  630. // continue until this event is signalled.
  631. //
  632. TRACE2(L"Failed to signal SC_OOBE_MACHINE_NAME_DONE(%s): 0x%08X\n",
  633. SC_OOBE_MACHINE_NAME_DONE, GetLastError());
  634. fReturn = FALSE;
  635. }
  636. MYASSERT(fReturn); // Why did we fail to set an open event??
  637. }
  638. return fReturn;
  639. }
  640. BOOL
  641. IsUserAdmin(
  642. VOID
  643. )
  644. /*++
  645. Routine Description:
  646. This routine returns TRUE if the caller's process is a
  647. member of the Administrators local group.
  648. Caller is NOT expected to be impersonating anyone and IS
  649. expected to be able to open their own process and process
  650. token.
  651. Arguments:
  652. None.
  653. Return Value:
  654. TRUE - Caller has Administrators local group.
  655. FALSE - Caller does not have Administrators local group.
  656. --*/
  657. {
  658. HANDLE Token;
  659. DWORD BytesRequired;
  660. PTOKEN_GROUPS Groups;
  661. BOOL b;
  662. DWORD i;
  663. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  664. PSID AdministratorsGroup;
  665. //
  666. // Open the process token.
  667. //
  668. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) {
  669. return(FALSE);
  670. }
  671. b = FALSE;
  672. Groups = NULL;
  673. //
  674. // Get group information.
  675. //
  676. if(!GetTokenInformation(Token,TokenGroups,NULL,0,&BytesRequired)
  677. && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  678. && (Groups = (PTOKEN_GROUPS)LocalAlloc(LPTR,BytesRequired))
  679. && GetTokenInformation(Token,TokenGroups,Groups,BytesRequired,&BytesRequired)) {
  680. b = AllocateAndInitializeSid(
  681. &NtAuthority,
  682. 2,
  683. SECURITY_BUILTIN_DOMAIN_RID,
  684. DOMAIN_ALIAS_RID_ADMINS,
  685. 0, 0, 0, 0, 0, 0,
  686. &AdministratorsGroup
  687. );
  688. if(b) {
  689. //
  690. // See if the user has the administrator group.
  691. //
  692. b = FALSE;
  693. for(i=0; i<Groups->GroupCount; i++) {
  694. if(EqualSid(Groups->Groups[i].Sid,AdministratorsGroup)) {
  695. b = TRUE;
  696. break;
  697. }
  698. }
  699. FreeSid(AdministratorsGroup);
  700. }
  701. }
  702. //
  703. // Clean up and return.
  704. //
  705. if(Groups) {
  706. LocalFree((HLOCAL)Groups);
  707. }
  708. CloseHandle(Token);
  709. return(b);
  710. }
  711. #define MyMalloc(s) GlobalAlloc(GPTR, s)
  712. #define MyFree(p) GlobalFree(p)
  713. static LPTSTR
  714. pDuplicateString(
  715. LPCTSTR szText
  716. )
  717. {
  718. int cchText;
  719. LPTSTR szOutText;
  720. if (szText == NULL)
  721. {
  722. return NULL;
  723. }
  724. cchText = lstrlen(szText);
  725. szOutText = (LPTSTR) MyMalloc(sizeof(TCHAR) * (cchText + 1));
  726. if (szOutText)
  727. {
  728. lstrcpyn(szOutText, szText, cchText + 1);
  729. }
  730. return szOutText;
  731. }
  732. PSTRINGLIST
  733. CreateStringCell (
  734. IN PCTSTR String
  735. )
  736. {
  737. PSTRINGLIST p = (PSTRINGLIST) MyMalloc (sizeof (STRINGLIST));
  738. if (p) {
  739. ZeroMemory (p, sizeof (STRINGLIST));
  740. if (String) {
  741. p->String = pDuplicateString (String);
  742. if (!p->String) {
  743. MyFree (p);
  744. p = NULL;
  745. }
  746. } else {
  747. p->String = NULL;
  748. }
  749. }
  750. return p;
  751. }
  752. VOID
  753. DeleteStringCell (
  754. IN PSTRINGLIST Cell
  755. )
  756. {
  757. if (Cell) {
  758. MyFree (Cell->String);
  759. MyFree (Cell);
  760. }
  761. }
  762. BOOL
  763. InsertList (
  764. IN OUT PSTRINGLIST* List,
  765. IN PSTRINGLIST NewList
  766. )
  767. {
  768. PSTRINGLIST p;
  769. if (!NewList) {
  770. return FALSE;
  771. }
  772. if (*List) {
  773. for (p = *List; p->Next; p = p->Next) ;
  774. p->Next = NewList;
  775. } else {
  776. *List = NewList;
  777. }
  778. return TRUE;
  779. }
  780. VOID
  781. DestroyList (
  782. IN PSTRINGLIST List
  783. )
  784. {
  785. PSTRINGLIST p, q;
  786. for (p = List; p; p = q) {
  787. q = p->Next;
  788. DeleteStringCell (p);
  789. }
  790. }
  791. BOOL
  792. RemoveListI(
  793. IN OUT PSTRINGLIST* List,
  794. IN PCTSTR String
  795. )
  796. {
  797. PSTRINGLIST p = *List;
  798. BOOL b = FALSE;
  799. if (p)
  800. {
  801. if (!lstrcmpi(p->String, String))
  802. {
  803. *List = p->Next;
  804. DeleteStringCell(p);
  805. b = TRUE;
  806. }
  807. else
  808. {
  809. PSTRINGLIST q;
  810. for (q = p->Next; q; p = q, q = q->Next)
  811. {
  812. if (!lstrcmpi(q->String, String))
  813. {
  814. p->Next = q->Next;
  815. DeleteStringCell(q);
  816. b = TRUE;
  817. break;
  818. }
  819. }
  820. }
  821. }
  822. return b;
  823. }
  824. BOOL
  825. ExistInListI(
  826. IN PSTRINGLIST List,
  827. IN PCTSTR String
  828. )
  829. {
  830. PSTRINGLIST p;
  831. for (p = List; p; p = p->Next)
  832. {
  833. if (!lstrcmpi(p->String, String))
  834. {
  835. break;
  836. }
  837. }
  838. return (p != NULL);
  839. }
  840. BOOL IsDriveNTFS(IN TCHAR Drive)
  841. {
  842. TCHAR DriveName[4];
  843. TCHAR Filesystem[256];
  844. TCHAR VolumeName[MAX_PATH];
  845. DWORD SerialNumber;
  846. DWORD MaxComponent;
  847. DWORD Flags;
  848. BOOL bIsNTFS = FALSE;
  849. DriveName[0] = Drive;
  850. DriveName[1] = TEXT(':');
  851. DriveName[2] = TEXT('\\');
  852. DriveName[3] = 0;
  853. if (GetVolumeInformation(
  854. DriveName,
  855. VolumeName,MAX_PATH,
  856. &SerialNumber,
  857. &MaxComponent,
  858. &Flags,
  859. Filesystem,
  860. sizeof(Filesystem)/sizeof(TCHAR)
  861. ))
  862. {
  863. bIsNTFS = (lstrcmpi(Filesystem,TEXT("NTFS")) == 0);
  864. }
  865. return bIsNTFS;
  866. }
  867. BOOL
  868. HasTablet()
  869. {
  870. TCHAR szPath[MAX_PATH+1];
  871. ZeroMemory(szPath, sizeof(szPath));
  872. if (FAILED(SHGetFolderPath(
  873. NULL,
  874. CSIDL_PROGRAM_FILES_COMMON,
  875. NULL,
  876. SHGFP_TYPE_DEFAULT,
  877. szPath)))
  878. {
  879. return FALSE;
  880. }
  881. StrCatBuff(szPath, TEXT("\\Microsoft Shared\\Ink\\tabtip.exe"), MAX_PATH+1);
  882. return PathFileExists(szPath);
  883. }
  884. DWORD
  885. MyGetModuleFileName (
  886. IN HMODULE Module,
  887. OUT PTSTR Buffer,
  888. IN DWORD BufferLength
  889. )
  890. {
  891. DWORD d = GetModuleFileName (Module, Buffer, BufferLength);
  892. if (BufferLength > 0)
  893. {
  894. Buffer[BufferLength - 1] = 0;
  895. }
  896. if (d < BufferLength)
  897. {
  898. return d;
  899. }
  900. else
  901. {
  902. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  903. return 0;
  904. }
  905. }