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.

882 lines
20 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. Client Side Utility Routines
  7. Author:
  8. Dave Snipp (DaveSn) 15-Mar-1991
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "client.h"
  14. HANDLE hCSR = INVALID_HANDLE_VALUE;
  15. BOOL
  16. InCSRProcess(
  17. VOID
  18. )
  19. {
  20. //
  21. // hCSR == INVALID_HANDLE_VALUE Not initialized, must check.
  22. // NULL Not running in CSR
  23. // hModule value Running in CSR
  24. //
  25. if (hCSR != NULL) {
  26. //
  27. // Check if we are running in CSR. If so, then don't try
  28. // any notifications.
  29. //
  30. if (hCSR == INVALID_HANDLE_VALUE) {
  31. hCSR = GetModuleHandle( gszCSRDll );
  32. }
  33. }
  34. return hCSR != NULL;
  35. }
  36. LPVOID
  37. DllAllocSplMem(
  38. DWORD cb
  39. )
  40. /*++
  41. Routine Description:
  42. This function will allocate local memory. It will possibly allocate extra
  43. memory and fill this with debugging information for the debugging version.
  44. Arguments:
  45. cb - The amount of memory to allocate
  46. Return Value:
  47. NON-NULL - A pointer to the allocated memory
  48. FALSE/NULL - The operation failed. Extended error status is available
  49. using GetLastError.
  50. --*/
  51. {
  52. PDWORD_PTR pMem;
  53. DWORD cbNew;
  54. cb = DWORD_ALIGN_UP(cb);
  55. cbNew = cb+sizeof(DWORD_PTR)+sizeof(DWORD);
  56. pMem= LocalAlloc(LPTR, cbNew);
  57. if (!pMem) {
  58. DBGMSG( DBG_WARNING, ("Memory Allocation failed for %d bytes\n", cbNew ));
  59. return 0;
  60. }
  61. *pMem=cb;
  62. *(LPDWORD)((LPBYTE)pMem+cbNew-sizeof(DWORD))=0xdeadbeef;
  63. return (LPVOID)(pMem+1);
  64. }
  65. BOOL
  66. DllFreeSplMem(
  67. LPVOID pMem
  68. )
  69. {
  70. DWORD_PTR cbNew;
  71. PDWORD_PTR pNewMem;
  72. if( !pMem ){
  73. return TRUE;
  74. }
  75. pNewMem = pMem;
  76. pNewMem--;
  77. cbNew = *pNewMem;
  78. if (*(LPDWORD)((LPBYTE)pMem + cbNew) != 0xdeadbeef) {
  79. DBGMSG(DBG_ERROR, ("DllFreeSplMem Corrupt Memory in winspool : %0p\n", pNewMem));
  80. return FALSE;
  81. }
  82. memset(pNewMem, 0x65, (size_t) cbNew);
  83. LocalFree((LPVOID)pNewMem);
  84. return TRUE;
  85. }
  86. LPVOID
  87. ReallocSplMem(
  88. LPVOID pOldMem,
  89. DWORD cbOld,
  90. DWORD cbNew
  91. )
  92. {
  93. LPVOID pNewMem;
  94. pNewMem=AllocSplMem(cbNew);
  95. if (pOldMem && pNewMem) {
  96. if (cbOld) {
  97. CopyMemory( pNewMem, pOldMem, min(cbNew, cbOld));
  98. }
  99. FreeSplMem(pOldMem);
  100. }
  101. return pNewMem;
  102. }
  103. LPTSTR
  104. AllocSplStr(
  105. LPCTSTR pStr
  106. )
  107. /*++
  108. Routine Description:
  109. This function will allocate enough local memory to store the specified
  110. string, and copy that string to the allocated memory
  111. Arguments:
  112. pStr - Pointer to the string that needs to be allocated and stored
  113. Return Value:
  114. NON-NULL - A pointer to the allocated memory containing the string
  115. FALSE/NULL - The operation failed. Extended error status is available
  116. using GetLastError.
  117. --*/
  118. {
  119. LPTSTR pMem;
  120. if (!pStr)
  121. return 0;
  122. if (pMem = AllocSplMem( _tcslen(pStr)*sizeof(TCHAR) + sizeof(TCHAR) ))
  123. StringCchCopy(pMem, _tcslen(pStr)+1, pStr);
  124. return pMem;
  125. }
  126. BOOL
  127. DllFreeSplStr(
  128. LPTSTR pStr
  129. )
  130. {
  131. return pStr ?
  132. DllFreeSplMem(pStr) :
  133. FALSE;
  134. }
  135. BOOL
  136. ReallocSplStr(
  137. LPTSTR *ppStr,
  138. LPCTSTR pStr
  139. )
  140. {
  141. LPWSTR pOldStr = *ppStr;
  142. *ppStr=AllocSplStr(pStr);
  143. FreeSplStr(pOldStr);
  144. return TRUE;
  145. }
  146. /* Message
  147. *
  148. * Displays a message by loading the strings whose IDs are passed into
  149. * the function, and substituting the supplied variable argument list
  150. * using the varargs macros.
  151. *
  152. */
  153. INT
  154. Message(
  155. HWND hwnd,
  156. DWORD Type,
  157. INT CaptionID,
  158. INT TextID,
  159. ...
  160. )
  161. {
  162. TCHAR MsgText[256];
  163. TCHAR MsgFormat[256];
  164. TCHAR MsgCaption[40];
  165. va_list vargs;
  166. if( ( LoadString( hInst, TextID, MsgFormat,
  167. COUNTOF(MsgFormat)) > 0 )
  168. && ( LoadString( hInst, CaptionID, MsgCaption, COUNTOF(MsgCaption) ) > 0 ) )
  169. {
  170. va_start( vargs, TextID );
  171. StringCchVPrintf( MsgText, 256, MsgFormat, vargs );
  172. va_end( vargs );
  173. return MessageBox( hwnd, MsgText, MsgCaption, Type );
  174. }
  175. else
  176. return 0;
  177. }
  178. /*
  179. *
  180. */
  181. LPTSTR
  182. GetErrorString(
  183. DWORD Error
  184. )
  185. {
  186. TCHAR Buffer[1024];
  187. LPTSTR pErrorString = NULL;
  188. DWORD dwFlags;
  189. HANDLE hModule;
  190. if ((Error >= NERR_BASE) && (Error <= MAX_NERR)){
  191. hModule = LoadLibrary(szNetMsgDll);
  192. dwFlags = FORMAT_MESSAGE_FROM_HMODULE;
  193. }
  194. else {
  195. hModule = NULL;
  196. dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
  197. }
  198. if( FormatMessage( dwFlags, hModule,
  199. Error, 0, Buffer,
  200. COUNTOF(Buffer), NULL )
  201. == 0 )
  202. LoadString( hInst, IDS_UNKNOWN_ERROR, Buffer,
  203. COUNTOF(Buffer));
  204. pErrorString = AllocSplStr(Buffer);
  205. if (hModule) {
  206. FreeLibrary(hModule);
  207. }
  208. return pErrorString;
  209. }
  210. DWORD ReportFailure( HWND hwndParent,
  211. DWORD idTitle,
  212. DWORD idDefaultError )
  213. {
  214. DWORD ErrorID;
  215. DWORD MsgType;
  216. LPTSTR pErrorString;
  217. ErrorID = GetLastError( );
  218. MsgType = MB_OK | MB_ICONSTOP;
  219. pErrorString = GetErrorString( ErrorID );
  220. Message( hwndParent, MsgType, idTitle,
  221. idDefaultError, pErrorString );
  222. FreeSplStr( pErrorString );
  223. return ErrorID;
  224. }
  225. /*
  226. *
  227. */
  228. #define ENTRYFIELD_LENGTH 256
  229. LPTSTR AllocDlgItemText(HWND hwnd, int id)
  230. {
  231. TCHAR string[ENTRYFIELD_LENGTH];
  232. GetDlgItemText (hwnd, id, string, COUNTOF(string));
  233. return ( *string ? AllocSplStr(string) : NULL );
  234. }
  235. PSECURITY_DESCRIPTOR
  236. BuildInputSD(
  237. PSECURITY_DESCRIPTOR pPrinterSD,
  238. PDWORD pSizeSD
  239. )
  240. /*++
  241. --*/
  242. {
  243. SECURITY_DESCRIPTOR AbsoluteSD;
  244. PSECURITY_DESCRIPTOR pRelative;
  245. BOOL Defaulted = FALSE;
  246. BOOL DaclPresent = FALSE;
  247. BOOL SaclPresent = FALSE;
  248. PSID pOwnerSid = NULL;
  249. PSID pGroupSid = NULL;
  250. PACL pDacl = NULL;
  251. PACL pSacl = NULL;
  252. DWORD SDLength = 0;
  253. //
  254. // Initialize *pSizeSD = 0;
  255. //
  256. *pSizeSD = 0;
  257. if (!IsValidSecurityDescriptor(pPrinterSD)) {
  258. return(NULL);
  259. }
  260. if (!InitializeSecurityDescriptor (&AbsoluteSD, SECURITY_DESCRIPTOR_REVISION1)) {
  261. return(NULL);
  262. }
  263. if(!GetSecurityDescriptorOwner(pPrinterSD,
  264. &pOwnerSid, &Defaulted)){
  265. return(NULL);
  266. }
  267. SetSecurityDescriptorOwner(&AbsoluteSD,
  268. pOwnerSid, Defaulted );
  269. if(! GetSecurityDescriptorGroup( pPrinterSD,
  270. &pGroupSid, &Defaulted )){
  271. return(NULL);
  272. }
  273. SetSecurityDescriptorGroup( &AbsoluteSD,
  274. pGroupSid, Defaulted );
  275. if(!GetSecurityDescriptorDacl( pPrinterSD,
  276. &DaclPresent, &pDacl, &Defaulted )){
  277. return(NULL);
  278. }
  279. SetSecurityDescriptorDacl( &AbsoluteSD,
  280. DaclPresent, pDacl, Defaulted );
  281. if(!GetSecurityDescriptorSacl( pPrinterSD,
  282. &SaclPresent, &pSacl, &Defaulted)){
  283. return(NULL);
  284. }
  285. SetSecurityDescriptorSacl( &AbsoluteSD,
  286. SaclPresent, pSacl, Defaulted );
  287. SDLength = GetSecurityDescriptorLength( &AbsoluteSD);
  288. pRelative = LocalAlloc(LPTR, SDLength);
  289. if (!pRelative) {
  290. return(NULL);
  291. }
  292. if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &SDLength)) {
  293. LocalFree(pRelative);
  294. return(NULL);
  295. }
  296. *pSizeSD = SDLength;
  297. return(pRelative);
  298. }
  299. PKEYDATA
  300. CreateTokenList(
  301. LPWSTR pKeyData
  302. )
  303. {
  304. DWORD cTokens;
  305. DWORD cb;
  306. PKEYDATA pResult;
  307. LPWSTR pDest;
  308. LPWSTR psz = pKeyData;
  309. LPWSTR *ppToken;
  310. if (!psz || !*psz)
  311. return NULL;
  312. cTokens=1;
  313. /* Scan through the string looking for commas,
  314. * ensuring that each is followed by a non-NULL character:
  315. */
  316. while ((psz = wcschr(psz, L',')) && psz[1]) {
  317. cTokens++;
  318. psz++;
  319. }
  320. cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
  321. wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
  322. if (!(pResult = (PKEYDATA)AllocSplMem(cb)))
  323. return NULL;
  324. pResult->cb = cb;
  325. /* Initialise pDest to point beyond the token pointers:
  326. */
  327. pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
  328. (cTokens-1) * sizeof(LPWSTR));
  329. /* Then copy the key data buffer there:
  330. */
  331. StringCchCopy(pDest,
  332. (cb - sizeof(KEYDATA) - (cTokens-1) * sizeof(LPWSTR))/2,
  333. pKeyData);
  334. ppToken = pResult->pTokens;
  335. psz = pDest;
  336. do {
  337. *ppToken++ = psz;
  338. if ( psz = wcschr(psz, L',') )
  339. *psz++ = L'\0';
  340. } while (psz);
  341. pResult->cTokens = cTokens;
  342. return( pResult );
  343. }
  344. LPWSTR
  345. GetPrinterPortList(
  346. HANDLE hPrinter
  347. )
  348. {
  349. LPBYTE pMem;
  350. LPTSTR pPort;
  351. DWORD dwPassed = 1024; //Try 1K to start with
  352. LPPRINTER_INFO_2 pPrinter;
  353. DWORD dwLevel = 2;
  354. DWORD dwNeeded;
  355. PKEYDATA pKeyData;
  356. DWORD i = 0;
  357. LPWSTR pPortNames = NULL;
  358. pMem = AllocSplMem(dwPassed);
  359. if (pMem == NULL) {
  360. return FALSE;
  361. }
  362. if (!GetPrinter(hPrinter, dwLevel, pMem, dwPassed, &dwNeeded)) {
  363. DBGMSG(DBG_TRACE, ("Last error is %d\n", GetLastError()));
  364. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  365. return NULL;
  366. }
  367. pMem = ReallocSplMem(pMem, dwPassed, dwNeeded);
  368. dwPassed = dwNeeded;
  369. if (!GetPrinter(hPrinter, dwLevel, pMem, dwPassed, &dwNeeded)) {
  370. FreeSplMem(pMem);
  371. return (NULL);
  372. }
  373. }
  374. pPrinter = (LPPRINTER_INFO_2)pMem;
  375. //
  376. // Fixes the null pPrinter->pPortName problem where
  377. // downlevel may return null
  378. //
  379. if (!pPrinter->pPortName) {
  380. FreeSplMem(pMem);
  381. return(NULL);
  382. }
  383. pPortNames = AllocSplStr(pPrinter->pPortName);
  384. FreeSplMem(pMem);
  385. return(pPortNames);
  386. }
  387. BOOL
  388. UpdateString(
  389. IN LPCTSTR pszString, OPTIONAL
  390. OUT LPTSTR* ppszOut
  391. )
  392. /*++
  393. Routine Description:
  394. Updates an output string if the input is non-NULL.
  395. Arguments:
  396. pszString - String to update to. If NULL or -1, function does nothing.
  397. Return Value:
  398. TRUE - Success
  399. FALSE - FAILED. *ppszOut = NULL
  400. --*/
  401. {
  402. if( pszString && pszString != (LPCTSTR)-1 ){
  403. FreeSplStr( *ppszOut );
  404. *ppszOut = AllocSplStr( pszString );
  405. if( !*ppszOut ){
  406. return FALSE;
  407. }
  408. }
  409. return TRUE;
  410. }
  411. DWORD
  412. RouterFreeBidiResponseContainer(
  413. PBIDI_RESPONSE_CONTAINER pData
  414. )
  415. {
  416. BIDI_RESPONSE_DATA *p;
  417. DWORD Count = 0;
  418. DWORD NumOfRspns;
  419. DWORD dwRet = ERROR_SUCCESS;
  420. try
  421. {
  422. if(pData)
  423. {
  424. Count = pData->Count;
  425. for(NumOfRspns= 0,
  426. p = &pData->aData[0];
  427. NumOfRspns < Count;
  428. NumOfRspns++,
  429. p++
  430. )
  431. {
  432. if(p)
  433. {
  434. if(p->pSchema)
  435. {
  436. MIDL_user_free(p->pSchema);
  437. }
  438. switch(p->data.dwBidiType)
  439. {
  440. //
  441. // Text Data (ANSI String)
  442. //
  443. case BIDI_TEXT:
  444. //
  445. // String (UNICODE string)
  446. //
  447. case BIDI_ENUM:
  448. //
  449. // Enumeration Data (ANSI String)
  450. //
  451. case BIDI_STRING:
  452. {
  453. if(p->data.u.sData)
  454. {
  455. MIDL_user_free(p->data.u.sData);
  456. }
  457. }
  458. break;
  459. //
  460. // Binary Data (BLOB)
  461. //
  462. case BIDI_BLOB:
  463. {
  464. if(p->data.u.biData.pData)
  465. {
  466. MIDL_user_free(p->data.u.biData.pData);
  467. }
  468. }
  469. break;
  470. //
  471. // Undefined Type
  472. //
  473. default:
  474. {
  475. //
  476. // Nothing really , just return
  477. //
  478. }
  479. break;
  480. }
  481. }
  482. }
  483. MIDL_user_free(pData);
  484. }
  485. }
  486. except(1)
  487. {
  488. dwRet = TranslateExceptionCode(GetExceptionCode());
  489. DBGMSG(DBG_ERROR, ("RouterFreeBidiResponseContainer raised an exception : %u \n", dwRet));
  490. }
  491. return(dwRet);
  492. }
  493. ClientVersion
  494. GetClientVer()
  495. {
  496. ClientVersion ClientVer;
  497. return(ClientVer = sizeof(ULONG_PTR));
  498. }
  499. ServerVersion
  500. GetServerVer()
  501. {
  502. ULONG_PTR ul;
  503. NTSTATUS st;
  504. ServerVersion CurrVer;
  505. st = NtQueryInformationProcess(NtCurrentProcess(),
  506. ProcessWow64Information,
  507. &ul,
  508. sizeof(ul),
  509. NULL);
  510. if (NT_SUCCESS(st))
  511. {
  512. // If this call succeeds, we're on Win2000 or newer machines.
  513. if (0 != ul)
  514. {
  515. // 32-bit code running on Win64
  516. CurrVer = THUNKVERSION;
  517. } else
  518. {
  519. // 32-bit code running on Win2000 or later 32-bit OS
  520. CurrVer = NATIVEVERSION;
  521. }
  522. } else
  523. {
  524. CurrVer = NATIVEVERSION;
  525. }
  526. return(CurrVer);
  527. }
  528. BOOL
  529. RunInWOW64()
  530. {
  531. return((GetClientVer() == RUN32BINVER) &&
  532. (GetServerVer() == THUNKVERSION) &&
  533. !bLoadedBySpooler);
  534. /*return(bLoadedBySpooler ? FALSE : TRUE);*/
  535. }
  536. HWND
  537. GetForeGroundWindow(
  538. VOID
  539. )
  540. {
  541. //
  542. // get the foreground window first
  543. //
  544. HWND hWndOwner;
  545. HWND hWndLastPopup;
  546. HWND hWndForeground = GetForegroundWindow();
  547. //
  548. // climb up to the top parent in case it's a child window...
  549. //
  550. HWND hWndParent = hWndForeground;
  551. while ( hWndParent = GetParent(hWndParent) )
  552. {
  553. hWndForeground = hWndParent;
  554. }
  555. //
  556. // get the owner in case the top parent is owned
  557. //
  558. hWndOwner= GetWindow(hWndForeground, GW_OWNER);
  559. if ( hWndOwner )
  560. {
  561. hWndForeground = hWndOwner;
  562. }
  563. hWndLastPopup = GetLastActivePopup(hWndForeground);
  564. return(hWndLastPopup);
  565. }
  566. LPCWSTR
  567. FindFileName(
  568. IN LPCWSTR pPathName
  569. )
  570. /*++
  571. Routine Description:
  572. Retrieve the filename portion of a path.
  573. This will can the input string until it finds the last backslash,
  574. then return the portion of the string immediately following it.
  575. If the string terminates with a backslash, then NULL is returned.
  576. Note: this can return illegal file names; no validation is done.
  577. Arguments:
  578. pPathName - Path name to parse.
  579. Return Value:
  580. Last portion of file name or NULL if none available.
  581. --*/
  582. {
  583. LPCWSTR pSlash;
  584. LPCWSTR pTemp;
  585. if( !pPathName ){
  586. return NULL;
  587. }
  588. pTemp = pPathName;
  589. while( pSlash = wcschr( pTemp, L'\\' )) {
  590. pTemp = pSlash+1;
  591. }
  592. if( !*pTemp ){
  593. return NULL;
  594. }
  595. return pTemp;
  596. }
  597. /*++
  598. Name:
  599. BuildSpoolerObjectPath
  600. Description:
  601. This function addresses bug 461462. When the spooler is not running,
  602. this function can build the path to the drivers directory or the print
  603. processors directory. The result of this function is a path like:
  604. C:\Windows\System32\spool\Drivers\w32x86
  605. or
  606. C:\Windows\System32\spool\Prtprocs\w32x86
  607. depending on the pszPath argument.
  608. Arguments:
  609. pszPath - can be "drivers" or "prtprocs"
  610. pszName - must be NULL or ""
  611. pszEnvironment - can be "windows nt x86" etc. This argument must be validated by the caller
  612. (GetPrinterDriverDirectoryW and GetPrintProcessorDirectoryW)
  613. Level - must be 1
  614. pDriverDirectory - buffer where to store the path
  615. cbBuf - count of bytes in the buffer
  616. pcbNeeded - count of bytes needed to store the path
  617. Return Value:
  618. TRUE - the function succeeded, pDriverDirectory can be used
  619. FALSE - the function failed, pDriverDirectory cannot be used.
  620. Last error:
  621. This function sets the last error in both failure and success cases.
  622. --*/
  623. BOOL
  624. BuildSpoolerObjectPath(
  625. IN PCWSTR pszPath,
  626. IN PCWSTR pszName,
  627. IN PCWSTR pszEnvironment,
  628. IN DWORD Level,
  629. IN PBYTE pDriverDirectory,
  630. IN DWORD cbBuf,
  631. IN PDWORD pcbNeeded
  632. )
  633. {
  634. DWORD Error = ERROR_INVALID_PARAMETER;
  635. if (pcbNeeded && (!pszName || !*pszName))
  636. {
  637. HKEY hkRoot = NULL;
  638. HKEY hkEnv = NULL;
  639. DWORD cchDir = MAX_PATH;
  640. WCHAR szDir[MAX_PATH];
  641. Error = GetSystemWindowsDirectory(szDir, cchDir) ? ERROR_SUCCESS : GetLastError();
  642. if (Error == ERROR_SUCCESS &&
  643. (Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  644. gszRegEnvironments,
  645. 0,
  646. KEY_READ,
  647. &hkRoot)) == ERROR_SUCCESS &&
  648. (Error = RegOpenKeyEx(hkRoot,
  649. pszEnvironment,
  650. 0,
  651. KEY_READ,
  652. &hkEnv)) == ERROR_SUCCESS &&
  653. (Error = StrNCatBuff(szDir,
  654. cchDir,
  655. szDir,
  656. szSlash,
  657. gszSystem32Spool,
  658. szSlash,
  659. pszPath,
  660. szSlash,
  661. NULL)) == ERROR_SUCCESS)
  662. {
  663. DWORD Length = wcslen(szDir);
  664. DWORD cbAvailable = (cchDir - Length) * sizeof(WCHAR);
  665. if ((Error = RegQueryValueEx(hkEnv,
  666. gszEnivronmentDirectory,
  667. NULL,
  668. NULL,
  669. (PBYTE)&szDir[Length],
  670. &cbAvailable)) == ERROR_SUCCESS)
  671. {
  672. *pcbNeeded = (wcslen(szDir) + 1) * sizeof(WCHAR);
  673. if (cbBuf >= *pcbNeeded)
  674. {
  675. StringCchCopy((PWSTR)pDriverDirectory,
  676. cbBuf/2,
  677. szDir);
  678. }
  679. else
  680. {
  681. Error = ERROR_INSUFFICIENT_BUFFER;
  682. }
  683. }
  684. }
  685. else if (Error == ERROR_FILE_NOT_FOUND)
  686. {
  687. //
  688. // If we cannot open the "pszEnvironment" key then the environment is invalid.
  689. //
  690. Error = ERROR_INVALID_ENVIRONMENT;
  691. }
  692. if (hkRoot) RegCloseKey(hkRoot);
  693. if (hkEnv) RegCloseKey(hkEnv);
  694. }
  695. SetLastError(Error);
  696. return Error == ERROR_SUCCESS;
  697. }