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.

1682 lines
41 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. win32base.c
  5. Abstract:
  6. This module implements low level primitives that are win32 compatible.
  7. Author:
  8. clupu created 10/25/2000
  9. Revision History:
  10. --*/
  11. #include "sdbp.h"
  12. #include <time.h>
  13. #include <shlwapi.h>
  14. // Define this for bounds-checked detection of leaks.
  15. // #define BOUNDS_CHECKER_DETECTION
  16. //
  17. // Memory functions
  18. //
  19. void*
  20. SdbAlloc(
  21. IN size_t size // size in bytes to allocate
  22. )
  23. /*++
  24. Return: The pointer allocated.
  25. Desc: Just a wrapper for allocation -- perhaps useful if we move this
  26. code to a non-NTDLL location and need to call differently.
  27. --*/
  28. {
  29. return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
  30. }
  31. void
  32. SdbFree(
  33. IN void* pWhat // ptr allocated with SdbAlloc that should be freed.
  34. )
  35. /*++
  36. Return: The pointer allocated.
  37. Desc: Just a wrapper for deallocation -- perhaps useful if we move this
  38. code to a non-NTDLL location and need to call differently.
  39. --*/
  40. {
  41. HeapFree(GetProcessHeap(), 0, pWhat);
  42. }
  43. HANDLE
  44. SdbpOpenFile(
  45. IN LPCTSTR szPath, // full path of file to open
  46. IN PATH_TYPE eType // must be always DOS_PATH
  47. )
  48. /*++
  49. Return: A handle to the opened file or INVALID_HANDLE_VALUE on failure.
  50. Desc: Just a wrapper for opening an existing file for READ.
  51. --*/
  52. {
  53. HANDLE hFile;
  54. assert(eType == DOS_PATH);
  55. hFile = CreateFile(szPath,
  56. GENERIC_READ,
  57. FILE_SHARE_READ,
  58. NULL,
  59. OPEN_EXISTING,
  60. 0,
  61. NULL);
  62. if (hFile == INVALID_HANDLE_VALUE) {
  63. DBGPRINT((sdlInfo, "SdbpOpenFile", "CreateFileW failed 0x%x.\n", GetLastError()));
  64. }
  65. return hFile;
  66. }
  67. void
  68. SdbpQueryAppCompatFlagsForExeID(
  69. IN HKEY hkeyRoot, // the root key (HKLM or HKCU)
  70. IN LPCTSTR pwszExeID, // the exe ID in string format
  71. OUT LPDWORD lpdwFlags // this will contain the flags from the registry.
  72. )
  73. /*++
  74. Return: void.
  75. Desc: BUGBUG
  76. Query registry for compatibility flags. Exe ID is a GUID in string format.
  77. --*/
  78. {
  79. HKEY hkey;
  80. DWORD type, cbSize, dwFlags = 0;
  81. LONG lRes;
  82. *lpdwFlags = 0;
  83. lRes = RegOpenKey(hkeyRoot, APPCOMPAT_KEY_PATH, &hkey);
  84. if (lRes != ERROR_SUCCESS) {
  85. //
  86. // No key for this ExeID. No big deal.
  87. //
  88. return;
  89. }
  90. cbSize = sizeof(DWORD);
  91. lRes = RegQueryValueEx(hkey, pwszExeID, NULL, &type, (LPBYTE)&dwFlags, &cbSize);
  92. if (lRes != ERROR_SUCCESS || type != REG_DWORD) {
  93. goto cleanup;
  94. }
  95. *lpdwFlags = dwFlags;
  96. cleanup:
  97. RegCloseKey(hkey);
  98. }
  99. BOOL
  100. SdbGetEntryFlags(
  101. IN GUID* pGuid, // the EXE's ID
  102. OUT LPDWORD lpdwFlags // will receive the flags for this EXE
  103. )
  104. /*++
  105. Return: void.
  106. Desc: BUGBUG: comment.
  107. --*/
  108. {
  109. TCHAR szExeID[128];
  110. DWORD dwFlagsMachine = 0, dwFlagsUser = 0;
  111. if (!SdbGUIDToString(pGuid, szExeID)) {
  112. DBGPRINT((sdlError, "SdbGetEntryFlags",
  113. "Failed to convert guid to string\n"));
  114. return FALSE;
  115. }
  116. //
  117. // Look in both the local machine and per user keys. Then combine the
  118. // flags.
  119. //
  120. SdbpQueryAppCompatFlagsForExeID(HKEY_LOCAL_MACHINE, szExeID, &dwFlagsMachine);
  121. SdbpQueryAppCompatFlagsForExeID(HKEY_CURRENT_USER, szExeID, &dwFlagsUser);
  122. *lpdwFlags = (dwFlagsMachine | dwFlagsUser);
  123. return TRUE;
  124. }
  125. BOOL
  126. SdbSetEntryFlags(
  127. IN GUID* pGuid, // the EXE's ID
  128. IN DWORD dwFlags // the registry flags for this EXE
  129. )
  130. /*++
  131. Return: void.
  132. Desc: BUGBUG: comment.
  133. --*/
  134. {
  135. TCHAR szExeID[128];
  136. DWORD dwExeFlags;
  137. HKEY hkey;
  138. LONG lRes;
  139. lRes = RegCreateKey(HKEY_CURRENT_USER, APPCOMPAT_KEY_PATH, &hkey);
  140. if (lRes != ERROR_SUCCESS) {
  141. DBGPRINT((sdlError,
  142. "SdbSetEntryFlags",
  143. "Failed 0x%x to open/create key in HKCU\n",
  144. GetLastError()));
  145. return FALSE;
  146. }
  147. if (!SdbGUIDToString(pGuid, szExeID)) {
  148. DBGPRINT((sdlError, "SdbSetEntryFlags",
  149. "Failed to convert GUID to string\n"));
  150. RegCloseKey(hkey);
  151. return FALSE;
  152. }
  153. dwExeFlags = dwFlags;
  154. lRes = RegSetValueEx(hkey,
  155. szExeID,
  156. 0,
  157. REG_DWORD,
  158. (const BYTE*)&dwExeFlags,
  159. sizeof(DWORD));
  160. if (lRes != ERROR_SUCCESS) {
  161. DBGPRINT((sdlError,
  162. "SdbSetEntryFlags",
  163. "Failed 0x%x to set the flags for exe ID.\n",
  164. GetLastError()));
  165. return FALSE;
  166. }
  167. return TRUE;
  168. }
  169. VOID
  170. SdbpCleanupUserSDBCache(
  171. IN PSDBCONTEXT pSdbContext
  172. )
  173. {
  174. ;
  175. }
  176. BOOL
  177. SDBAPI
  178. SdbGetNthUserSdb(
  179. IN HSDB hSDB,
  180. IN LPCTSTR szItemName, // file name (foo.exe) or layer name
  181. IN BOOL bLayer, // true if layer
  182. IN OUT LPDWORD pdwIndex, // 0-based index
  183. OUT GUID* pGuidDB // guid of a database to search
  184. )
  185. {
  186. TCHAR szFullKey[512];
  187. LONG lResult;
  188. HKEY hKey = NULL;
  189. DWORD dwNameSize = 0;
  190. DWORD dwDataType;
  191. BOOL bRet = FALSE;
  192. TCHAR szSdbName[MAX_PATH];
  193. DWORD dwIndex = *pdwIndex;
  194. LPTSTR pDot;
  195. if (szItemName == NULL || pGuidDB == NULL || pdwIndex == NULL) {
  196. DBGPRINT((sdlError, "SdbGetNthUserSdb",
  197. "NULL parameter passed for szExeName or pGuidDB or pdwIndex.\n"));
  198. goto out;
  199. }
  200. if (bLayer) {
  201. _stprintf(szFullKey, TEXT("%s\\Layers\\%s"), APPCOMPAT_KEY_PATH_CUSTOM, szItemName);
  202. } else {
  203. _stprintf(szFullKey, TEXT("%s\\%s"), APPCOMPAT_KEY_PATH_CUSTOM, szItemName);
  204. }
  205. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  206. szFullKey,
  207. 0,
  208. KEY_READ,
  209. &hKey);
  210. if (lResult != ERROR_SUCCESS) {
  211. DBGPRINT((sdlInfo, "SdbGetNthUserSdb",
  212. "Failed to open Key \"%s\" Error 0x%x\n", szFullKey, lResult));
  213. goto out;
  214. }
  215. //
  216. // enum all the values please
  217. //
  218. while (TRUE) {
  219. dwNameSize = CHARCOUNT(szSdbName);
  220. lResult = RegEnumValue(hKey,
  221. dwIndex,
  222. szSdbName,
  223. &dwNameSize,
  224. NULL,
  225. &dwDataType,
  226. NULL,
  227. NULL);
  228. dwIndex++;
  229. if (lResult != ERROR_SUCCESS) {
  230. goto out;
  231. }
  232. //
  233. // we have sdb name, convert it to guid
  234. //
  235. pDot = _tcsrchr(szSdbName, TEXT('.'));
  236. if (pDot != NULL) {
  237. *pDot = TEXT('\0'); // old style entry
  238. }
  239. if (SdbGUIDFromString(szSdbName, pGuidDB)) {
  240. //
  241. // we are done
  242. //
  243. break;
  244. }
  245. }
  246. //
  247. // advance the counter if success
  248. //
  249. *pdwIndex = dwIndex;
  250. bRet = TRUE;
  251. out:
  252. if (hKey != NULL) {
  253. RegCloseKey(hKey);
  254. }
  255. return bRet;
  256. }
  257. //
  258. // These three functions are not needed for Win9x, and are stubbed out here
  259. //
  260. BOOL
  261. SdbGetPermLayerKeys(
  262. IN LPCTSTR szPath,
  263. OUT LPTSTR szLayers,
  264. IN LPDWORD pdwBytes,
  265. IN DWORD dwFlags
  266. )
  267. {
  268. return FALSE;
  269. }
  270. BOOL
  271. SdbSetPermLayerKeys(
  272. IN LPCTSTR szPath,
  273. IN LPCTSTR szLayers,
  274. IN BOOL bMachine
  275. )
  276. {
  277. return FALSE;
  278. }
  279. BOOL
  280. SdbDeletePermLayerKeys(
  281. IN LPCTSTR szPath,
  282. IN BOOL bMachine
  283. )
  284. {
  285. return FALSE;
  286. }
  287. BOOL
  288. SdbpGetLongFileName(
  289. IN LPCTSTR szFullPath, // a full UNC or DOS path & filename, "c:\foo\mylong~1.ext"
  290. OUT LPTSTR szLongFileName // the long filename portion "mylongfilename.ext"
  291. )
  292. /*++
  293. Return: TRUE on success, FALSE otherwise.
  294. Desc: BUGBUG: comment.
  295. --*/
  296. {
  297. HANDLE hFind = INVALID_HANDLE_VALUE;
  298. WIN32_FIND_DATA FindData;
  299. BOOL bReturn = FALSE;
  300. hFind = FindFirstFile(szFullPath, &FindData);
  301. if (hFind == INVALID_HANDLE_VALUE) {
  302. DBGPRINT((sdlError,
  303. "SdbpGetLongFileName",
  304. "FindFirstFile failed, error 0x%x.\n",
  305. GetLastError()));
  306. goto Done;
  307. }
  308. //
  309. // BUGBUG: Hopefuly there is enough space in 'szLongFileName' to not AV :-(
  310. //
  311. _tcscpy(szLongFileName, FindData.cFileName);
  312. bReturn = TRUE;
  313. Done:
  314. if (hFind != INVALID_HANDLE_VALUE) {
  315. FindClose(hFind);
  316. }
  317. return bReturn;
  318. }
  319. void
  320. SdbpGetWinDir(
  321. OUT LPTSTR pszDir // will contain the %windir% path.
  322. )
  323. /*++
  324. Return: void.
  325. Desc: This is a wrapper function to get the windows directory.
  326. --*/
  327. {
  328. UINT cch;
  329. //
  330. // BUGBUG: This will only work properly on non-TS system.
  331. // On TS we need to use GetSystemWindowsDirectory instead.
  332. //
  333. cch = GetWindowsDirectory(pszDir, MAX_PATH);
  334. if (cch == 0) {
  335. *pszDir = 0;
  336. }
  337. }
  338. void
  339. SdbpGetAppPatchDir(
  340. OUT LPTSTR szAppPatchPath // will contain %windir%\AppPatch path
  341. )
  342. /*++
  343. Return: void.
  344. Desc: This is a wrapper function to get the %windir%\AppPatch directory.
  345. --*/
  346. {
  347. UINT cch;
  348. //
  349. // BUGBUG: This will only work properly on non-TS system.
  350. // On TS we need to use GetSystemWindowsDirectory instead.
  351. //
  352. cch = GetWindowsDirectory(szAppPatchPath, MAX_PATH);
  353. //
  354. // Make sure the path doesn't end with '\\'
  355. //
  356. if (cch > 0 && _T('\\') == szAppPatchPath[cch - 1]) {
  357. szAppPatchPath[cch - 1] = _T('\0');
  358. }
  359. _tcscat(szAppPatchPath, _T("\\AppPatch"));
  360. }
  361. void
  362. SdbpGetCurrentTime(
  363. OUT LPSYSTEMTIME lpTime // will contain the local time
  364. )
  365. /*++
  366. Return: void.
  367. Desc: This is a wrapper function to get the local time.
  368. --*/
  369. {
  370. GetLocalTime(lpTime);
  371. }
  372. NTSTATUS
  373. SdbpGetEnvVar(
  374. IN LPCTSTR pEnvironment,
  375. IN LPCTSTR pszVariableName,
  376. OUT LPTSTR pszVariableValue,
  377. OUT LPDWORD pdwBufferSize
  378. )
  379. /*++
  380. Return: BUGBUG: ?
  381. Desc: Retrieves the value of the specified environment variable.
  382. --*/
  383. {
  384. DWORD dwLength;
  385. DWORD dwBufferSize = 0;
  386. NTSTATUS Status;
  387. LPTSTR pszBuffer = NULL;
  388. assert(pEnvironment == NULL);
  389. if (pdwBufferSize && pszVariableValue) {
  390. dwBufferSize = *pdwBufferSize;
  391. }
  392. dwLength = GetEnvironmentVariable(pszVariableName, (LPTSTR)pszVariableValue, dwBufferSize);
  393. if (dwLength == 0) {
  394. //
  395. // The variable was not found. Just return.
  396. //
  397. return STATUS_VARIABLE_NOT_FOUND;
  398. }
  399. if (dwLength >= dwBufferSize) {
  400. Status = STATUS_BUFFER_TOO_SMALL;
  401. } else {
  402. Status = STATUS_SUCCESS;
  403. }
  404. if (pdwBufferSize != NULL) {
  405. *pdwBufferSize = dwLength;
  406. }
  407. return Status;
  408. }
  409. LPSTR
  410. SdbpFastUnicodeToAnsi(
  411. IN PDB pdb, // pointer to the database
  412. IN LPCWSTR pwszSrc, // String to convert
  413. IN TAG_TYPE ttTag, // tag type from which pwszSrc was obtained,
  414. // either STRINGREF or STRING
  415. IN DWORD dwRef // tagid or string's stringref
  416. )
  417. /*++
  418. Return: The pointer to the ANSI string in the hash table.
  419. Desc: This function converts a UNICODE string to ANSI and stores it in a hash
  420. table. It then returns the pointer to the ANSI string in the hash table.
  421. Subsequent calls trying to convert a string that has been previously
  422. converted will be very fast.
  423. --*/
  424. {
  425. LPSTR pszDest = NULL;
  426. PSTRHASH pHash = NULL;
  427. INT nSize;
  428. LPSTR pszBuffer = NULL;
  429. //
  430. // See if this string comes from the stringtable or it is in-place.
  431. //
  432. switch (ttTag) {
  433. case TAG_TYPE_STRING:
  434. if (pdb->pHashStringBody == NULL) {
  435. pdb->pHashStringBody = HashCreate();
  436. }
  437. pHash = pdb->pHashStringBody;
  438. break;
  439. case TAG_TYPE_STRINGREF:
  440. if (pdb->pHashStringTable == NULL) {
  441. pdb->pHashStringTable = HashCreate();
  442. }
  443. pHash = pdb->pHashStringTable;
  444. break;
  445. default:
  446. DBGPRINT((sdlError,
  447. "SdbpFastUnicodeToAnsi",
  448. "ttTag 0x%x should be STRING or STRINGREF\n",
  449. ttTag));
  450. assert(FALSE);
  451. break;
  452. }
  453. if (pHash == NULL) {
  454. DBGPRINT((sdlError,
  455. "SdbpFastUnicodeToAnsi",
  456. "Pointer to hash is invalid, tag type 0x%x\n",
  457. ttTag));
  458. return NULL;
  459. }
  460. pszDest = HashFindStringByRef(pHash, dwRef);
  461. if (pszDest == NULL) {
  462. //
  463. // Convert the string to ANSI. Do it in 2 steps to find
  464. // the required size first.
  465. //
  466. nSize = WideCharToMultiByte(CP_OEMCP,
  467. 0,
  468. pwszSrc,
  469. -1,
  470. NULL,
  471. 0,
  472. NULL,
  473. NULL);
  474. if (nSize == 0) {
  475. DBGPRINT((sdlError,
  476. "SdbpFastUnicodeToAnsi",
  477. "WideCharToMultiByte failed 0x%x.\n",
  478. GetLastError()));
  479. goto Done;
  480. }
  481. STACK_ALLOC(pszBuffer, nSize); // size is in BYTES
  482. if (pszBuffer == NULL) {
  483. DBGPRINT((sdlError,
  484. "SdbpFastUnicodeToAnsi",
  485. "Failed to allocate 0x%x bytes on the stack.\n",
  486. nSize));
  487. goto Done;
  488. }
  489. nSize = WideCharToMultiByte(CP_OEMCP,
  490. 0,
  491. pwszSrc,
  492. -1,
  493. pszBuffer,
  494. nSize,
  495. NULL,
  496. NULL);
  497. if (nSize == 0) {
  498. DBGPRINT((sdlError,
  499. "UnicodeStringToString",
  500. "WideCharToMultiByte failed with buffer Error = 0x%lx\n",
  501. GetLastError()));
  502. goto Done;
  503. }
  504. //
  505. // Now we are ready to store the string in the hash table.
  506. //
  507. pszDest = HashAddStringByRef(pHash, pszBuffer, dwRef);
  508. }
  509. Done:
  510. if (pszBuffer != NULL) {
  511. STACK_FREE(pszBuffer);
  512. }
  513. return pszDest;
  514. }
  515. BOOL
  516. SdbpMapFile(
  517. IN HANDLE hFile, // handle to the open file (this is done previously)
  518. OUT PIMAGEFILEDATA pImageData // stores the mapping info
  519. )
  520. /*++
  521. Return: TRUE on success, FALSE otherwise.
  522. Desc: This function maps the view of a file in memory so that access operations
  523. on that file are faster.
  524. --*/
  525. {
  526. NTSTATUS Status;
  527. HANDLE hSection = NULL;
  528. SIZE_T ViewSize = 0;
  529. PVOID pBase = NULL;
  530. LARGE_INTEGER liFileSize;
  531. BOOL bSuccess = FALSE;
  532. MEMORY_BASIC_INFORMATION MemoryInfo;
  533. if (hFile == INVALID_HANDLE_VALUE) {
  534. DBGPRINT((sdlError,
  535. "SdbpMapFile",
  536. "Invalid parameter.\n"));
  537. return FALSE;
  538. }
  539. liFileSize.LowPart = GetFileSize(hFile, &liFileSize.HighPart);
  540. if (liFileSize.LowPart == (DWORD)-1) {
  541. DWORD dwError = GetLastError();
  542. if (dwError != NO_ERROR) {
  543. DBGPRINT((sdlError, "SdbpMapFile", "GetFileSize failed with 0x%x.\n", dwError));
  544. return FALSE;
  545. }
  546. }
  547. hSection = CreateFileMapping(hFile,
  548. NULL, // no inheritance
  549. PAGE_READONLY | SEC_COMMIT,
  550. 0,
  551. 0,
  552. NULL);
  553. if (hSection == NULL) {
  554. DBGPRINT((sdlError,
  555. "SdbpMapFile",
  556. "CreateFileMapping failed with 0x%x.\n",
  557. GetLastError()));
  558. return FALSE;
  559. }
  560. //
  561. // Now map the view.
  562. //
  563. pBase = MapViewOfFile(hSection,
  564. FILE_MAP_READ,
  565. 0,
  566. 0,
  567. 0);
  568. if (pBase == NULL) {
  569. CloseHandle(hSection);
  570. DBGPRINT((sdlError,
  571. "SdbpMapFile",
  572. "MapViewOfFile failed with 0x%x.\n",
  573. GetLastError()));
  574. return FALSE;
  575. }
  576. //
  577. // Why do you need both FileSize and ViewSize ?
  578. // Both FileSize and ViewSize are used in various places
  579. // need to re-examine why and how they're used - BUGBUG
  580. //
  581. VirtualQuery(pBase, &MemoryInfo, sizeof(MemoryInfo));
  582. pImageData->hFile = hFile;
  583. pImageData->hSection = hSection;
  584. pImageData->pBase = pBase;
  585. pImageData->ViewSize = MemoryInfo.RegionSize;
  586. pImageData->FileSize = liFileSize.QuadPart;
  587. return TRUE;
  588. }
  589. BOOL
  590. SdbpUnmapFile(
  591. IN PIMAGEFILEDATA pImageData // mapping info
  592. )
  593. /*++
  594. Return: TRUE on success, FALSE otherwise.
  595. Desc: This function unmaps the view of a file.
  596. --*/
  597. {
  598. if (pImageData->pBase) {
  599. UnmapViewOfFile(pImageData->pBase);
  600. pImageData->pBase = NULL;
  601. }
  602. if (pImageData->hSection) {
  603. CloseHandle(pImageData->hSection);
  604. pImageData->hSection = NULL;
  605. }
  606. pImageData->hFile = INVALID_HANDLE_VALUE;
  607. return TRUE;
  608. }
  609. LPTSTR
  610. SdbpDuplicateString(
  611. IN LPCTSTR pszSrc // pointer to the string to be duplicated
  612. )
  613. /*++
  614. Return: A pointer to the allocated duplicated string.
  615. Desc: Duplicates a string by allocating a copy from the heap.
  616. --*/
  617. {
  618. LPTSTR pszDest = NULL;
  619. int nSize;
  620. assert(pszSrc != NULL);
  621. nSize = (_tcslen(pszSrc) + 1) * sizeof(TCHAR);
  622. pszDest = (LPTSTR)SdbAlloc(nSize);
  623. if (pszDest == NULL) {
  624. DBGPRINT((sdlError,
  625. "SdbpDuplicateString",
  626. "Failed to allocate %d bytes.\n",
  627. nSize));
  628. return NULL;
  629. }
  630. RtlMoveMemory(pszDest, pszSrc, nSize);
  631. return pszDest;
  632. }
  633. BOOL
  634. SdbpReadStringToAnsi(
  635. IN PDB pdb,
  636. IN TAGID tiWhich,
  637. OUT LPSTR pszBuffer,
  638. IN DWORD dwBufferSize
  639. )
  640. /*++
  641. Return: TRUE on success, FALSE otherwise.
  642. Desc: Reads a string from the database and converts it to ANSI.
  643. --*/
  644. {
  645. WCHAR* pData;
  646. INT nch;
  647. pData = (WCHAR*)SdbpGetMappedTagData(pdb, tiWhich);
  648. if (pData == NULL) {
  649. DBGPRINT((sdlError,
  650. "SdbpReadStringToAnsi",
  651. "SdbpGetMappedTagData failed for TAGID 0x%x.\n",
  652. tiWhich));
  653. return FALSE;
  654. }
  655. nch = WideCharToMultiByte(CP_OEMCP,
  656. 0,
  657. pData,
  658. -1,
  659. pszBuffer,
  660. dwBufferSize * sizeof(TCHAR),
  661. NULL,
  662. NULL);
  663. if (nch == 0) {
  664. DBGPRINT((sdlError,
  665. "SdbpReadStringToAnsi",
  666. "WideCharToMultiByte failed with 0x%x.\n",
  667. GetLastError()));
  668. return FALSE;
  669. }
  670. return TRUE;
  671. }
  672. DWORD
  673. SdbpGetFileSize(
  674. IN HANDLE hFile // handle to the file to check the size of
  675. )
  676. /*++
  677. Return: The size of the file or 0 on failure.
  678. Desc: Gets the lower DWORD of the size of a file -- only
  679. works accurately with files smaller than 2GB.
  680. In general, since we're only interested in matching, we're
  681. fine just matching the least significant DWORD of the file size.
  682. --*/
  683. {
  684. return GetFileSize(hFile, NULL);
  685. }
  686. BOOL
  687. SdbpQueryFileDirectoryAttributes(
  688. IN LPCTSTR FilePath,
  689. OUT PFILEDIRECTORYATTRIBUTES pFileDirectoryAttributes
  690. )
  691. /*++
  692. Return: TRUE on success, FALSE otherwise.
  693. Desc: BUGBUG: ?
  694. --*/
  695. {
  696. WIN32_FIND_DATA FindData;
  697. HANDLE hFind;
  698. int i;
  699. ZeroMemory(pFileDirectoryAttributes, sizeof(*pFileDirectoryAttributes));
  700. hFind = FindFirstFile(FilePath, &FindData);
  701. if (hFind == INVALID_HANDLE_VALUE) {
  702. DBGPRINT((sdlError,
  703. "SdbpQueryFileDirectoryAttributes",
  704. "FindFirstFile failed with 0x%x.\n",
  705. GetLastError()));
  706. return FALSE;
  707. }
  708. //
  709. // Make sure we are not checking vlfs.
  710. //
  711. if (FindData.nFileSizeHigh != 0) {
  712. DBGPRINT((sdlError,
  713. "SdbpQueryFileDirectoryAttributes",
  714. "Checking vlf files (0x%x 0x%x) is not supported\n",
  715. FindData.nFileSizeHigh,
  716. FindData.nFileSizeLow));
  717. return FALSE;
  718. }
  719. pFileDirectoryAttributes->dwFlags |= FDA_FILESIZE;
  720. pFileDirectoryAttributes->dwFileSizeHigh = FindData.nFileSizeHigh;
  721. pFileDirectoryAttributes->dwFileSizeLow = FindData.nFileSizeLow;
  722. FindClose(hFind);
  723. return TRUE;
  724. }
  725. BOOL
  726. SdbpDoesFileExists(
  727. IN LPCTSTR pszFilePath // the full path of the file
  728. )
  729. /*++
  730. Return: TRUE on success, FALSE otherwise.
  731. Desc: Checks if the specified file exists.
  732. --*/
  733. {
  734. DWORD dwAttributes;
  735. dwAttributes = GetFileAttributes(pszFilePath);
  736. return (dwAttributes != (DWORD)-1);
  737. }
  738. BOOL
  739. SdbpGet16BitDescription(
  740. OUT LPTSTR* ppszDescription,
  741. IN PIMAGEFILEDATA pImageData
  742. )
  743. /*++
  744. Return: TRUE on success, FALSE otherwise.
  745. Desc: BUGBUG: ?
  746. --*/
  747. {
  748. BOOL bSuccess;
  749. CHAR szBuffer[256];
  750. LPTSTR pszDescription = NULL;
  751. bSuccess = SdbpQuery16BitDescription(szBuffer, pImageData);
  752. if (bSuccess) {
  753. pszDescription = SdbpDuplicateString(szBuffer);
  754. *ppszDescription = pszDescription;
  755. }
  756. return (pszDescription != NULL);
  757. }
  758. BOOL
  759. SdbpGet16BitModuleName(
  760. OUT LPTSTR* ppszModuleName,
  761. IN PIMAGEFILEDATA pImageData
  762. )
  763. /*++
  764. Return: TRUE on success, FALSE otherwise.
  765. Desc: BUGBUG: ?
  766. --*/
  767. {
  768. BOOL bSuccess;
  769. CHAR szBuffer[256];
  770. LPTSTR pszModuleName = NULL;
  771. bSuccess = SdbpQuery16BitModuleName(szBuffer, pImageData);
  772. if (bSuccess) {
  773. pszModuleName = SdbpDuplicateString(szBuffer);
  774. *ppszModuleName = pszModuleName;
  775. }
  776. return (pszModuleName != NULL);
  777. }
  778. PVOID
  779. SdbGetFileInfo(
  780. IN HSDB hSDB,
  781. IN LPCTSTR pszFilePath,
  782. IN HANDLE hFile OPTIONAL,
  783. IN LPVOID pImageBase OPTIONAL,
  784. IN DWORD dwImageSize OPTIONAL,
  785. IN BOOL bNoCache
  786. )
  787. /*++
  788. Return: BUGBUG: ?
  789. Desc: BUGBUG: ?
  790. --*/
  791. {
  792. PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB;
  793. LPTSTR FullPath;
  794. NTSTATUS Status;
  795. PFILEINFO pFileInfo = NULL;
  796. DWORD nBufferLength;
  797. DWORD cch;
  798. UNICODE_STRING FullPathU;
  799. //
  800. // See if we have info on this file. Get the full path first.
  801. //
  802. cch = GetFullPathName(pszFilePath, 0, NULL, NULL);
  803. if (cch == 0) {
  804. DBGPRINT((sdlError,
  805. "GetFileInfo",
  806. "GetFullPathName failed for \"%s\" with 0x%x.\n",
  807. pszFilePath,
  808. GetLastError()));
  809. return NULL;
  810. }
  811. nBufferLength = (cch + 1) * sizeof(TCHAR);
  812. STACK_ALLOC(FullPath, nBufferLength);
  813. if (FullPath == NULL) {
  814. DBGPRINT((sdlError,
  815. "GetFileInfo",
  816. "Failed to allocate %d bytes on the stack for full path.\n",
  817. nBufferLength));
  818. return NULL;
  819. }
  820. cch = GetFullPathName(pszFilePath,
  821. nBufferLength,
  822. FullPath,
  823. NULL);
  824. assert(cch <= nBufferLength);
  825. if (cch > nBufferLength || cch == 0) {
  826. DBGPRINT((sdlError,
  827. "GetFileInfo",
  828. "GetFullPathName failed for \"%s\" with 0x%x.\n",
  829. pszFilePath,
  830. GetLastError()));
  831. STACK_FREE(FullPath);
  832. return NULL;
  833. }
  834. if (!bNoCache) {
  835. pFileInfo = FindFileInfo(pContext, FullPath);
  836. }
  837. if (pFileInfo == NULL) {
  838. if (SdbpDoesFileExists(FullPath)) {
  839. pFileInfo = CreateFileInfo(pContext,
  840. FullPath,
  841. cch,
  842. hFile,
  843. pImageBase,
  844. dwImageSize,
  845. bNoCache);
  846. }
  847. }
  848. STACK_FREE(FullPath);
  849. return (PVOID)pFileInfo;
  850. }
  851. int
  852. GetShimDbgLevel(
  853. void
  854. )
  855. {
  856. TCHAR szDebugLevel[128];
  857. DWORD cch;
  858. INT iShimDebugLevel = 0;
  859. cch = GetEnvironmentVariable(TEXT("SHIM_DEBUG_LEVEL"),
  860. szDebugLevel,
  861. CHARCOUNT(szDebugLevel));
  862. if (cch != 0) {
  863. iShimDebugLevel = (int)_tcstol(szDebugLevel, NULL, 0);
  864. }
  865. return iShimDebugLevel;
  866. }
  867. BOOL
  868. SdbpWriteBitsToFile(
  869. LPCTSTR pszFile,
  870. PBYTE pBuffer,
  871. DWORD dwSize
  872. )
  873. /*++
  874. Return: TRUE on success, FALSE otherwise.
  875. Desc: Self explanatory.
  876. --*/
  877. {
  878. HANDLE hFile = INVALID_HANDLE_VALUE;
  879. BOOL bReturn = FALSE;
  880. DWORD dwBytesWritten;
  881. hFile = CreateFile(pszFile,
  882. GENERIC_READ | GENERIC_WRITE,
  883. 0, // no sharing
  884. NULL,
  885. CREATE_ALWAYS,
  886. FILE_ATTRIBUTE_NORMAL,
  887. NULL);
  888. if (hFile == INVALID_HANDLE_VALUE) {
  889. DBGPRINT((sdlError, "SdbpWriteBitsToFile",
  890. "Failed to create file \"%s\" Error 0x%lx.\n", pszFile, GetLastError()));
  891. goto cleanup;
  892. }
  893. if (!WriteFile(hFile, pBuffer, dwSize, &dwBytesWritten, NULL)) {
  894. DBGPRINT((sdlError, "SdbpWriteBitsToFile",
  895. "Failed to write bits to file \"%s\" Error 0x%lx\n", pszFile, GetLastError()));
  896. goto cleanup;
  897. }
  898. bReturn = TRUE;
  899. cleanup:
  900. if (hFile != INVALID_HANDLE_VALUE) {
  901. CloseHandle(hFile);
  902. }
  903. return bReturn;
  904. }
  905. /***
  906. * void _resetstkoflw(void) - Recovers from Stack Overflow
  907. *
  908. * Purpose:
  909. * Sets the guard page to its position before the stack overflow.
  910. *
  911. *******************************************************************************/
  912. VOID
  913. SdbResetStackOverflow(
  914. VOID
  915. )
  916. {
  917. LPBYTE pStack, pGuard, pStackBase, pCommitBase;
  918. MEMORY_BASIC_INFORMATION mbi;
  919. SYSTEM_INFO si;
  920. DWORD PageSize;
  921. // Use alloca() to get the current stack pointer
  922. pStack = _alloca(1);
  923. // Find the base of the stack.
  924. VirtualQuery(pStack, &mbi, sizeof mbi);
  925. pStackBase = mbi.AllocationBase;
  926. VirtualQuery(pStackBase, &mbi, sizeof mbi);
  927. if (mbi.State & MEM_RESERVE) {
  928. pCommitBase = (LPBYTE)mbi.AllocationBase + mbi.RegionSize;
  929. VirtualQuery(pCommitBase, &mbi, sizeof mbi);
  930. } else {
  931. pCommitBase = pStackBase;
  932. }
  933. //
  934. // Find the page just below where stack pointer currently points.
  935. //
  936. GetSystemInfo(&si);
  937. PageSize = si.dwPageSize;
  938. pGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize -1)) - PageSize);
  939. if ( pGuard < pStackBase) {
  940. //
  941. // We can't save this
  942. //
  943. return;
  944. }
  945. if (pGuard > pStackBase) {
  946. VirtualFree(pStackBase, pGuard -pStackBase, MEM_DECOMMIT);
  947. }
  948. VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE);
  949. VirtualProtect(pGuard, PageSize, PAGE_READWRITE | PAGE_GUARD, &PageSize);
  950. }
  951. DWORD
  952. SdbExpandEnvironmentStrings(
  953. IN LPCTSTR lpSrc,
  954. OUT LPTSTR lpDst,
  955. IN DWORD nSize)
  956. {
  957. return ExpandEnvironmentStrings(lpSrc, lpDst, nSize);
  958. }
  959. TCHAR g_szDatabasePath[] = TEXT("DatabasePath");
  960. TCHAR g_szDatabaseType[] = TEXT("DatabaseType");
  961. TCHAR g_szDatabaseDescription[] = TEXT("DatabaseDescription");
  962. BOOL
  963. SDBAPI
  964. SdbGetDatabaseRegPath(
  965. IN GUID* pguidDB,
  966. OUT LPTSTR pszDatabasePath,
  967. IN DWORD dwBufferSize // size (in tchars) of the buffer
  968. )
  969. {
  970. TCHAR szDatabaseID[64];
  971. INT nch;
  972. SdbGUIDToString(pguidDB, szDatabaseID);
  973. nch = _sntprintf(pszDatabasePath,
  974. (size_t)dwBufferSize,
  975. TEXT("%s\\%s"),
  976. APPCOMPAT_KEY_PATH_INSTALLEDSDB,
  977. szDatabaseID);
  978. return (nch > 0);
  979. }
  980. BOOL
  981. SDBAPI
  982. SdbUnregisterDatabase(
  983. IN GUID* pguidDB
  984. )
  985. /*++
  986. Unregisters a database so it's no longer available.
  987. --*/
  988. {
  989. TCHAR szFullKey[512];
  990. //
  991. // Form the key
  992. //
  993. if (!SdbGetDatabaseRegPath(pguidDB, szFullKey, CHARCOUNT(szFullKey))) {
  994. DBGPRINT((sdlError, "SdbUnregisterDatabase", "Failed to get database key path\n"));
  995. return FALSE;
  996. }
  997. return (SHDeleteKey(HKEY_LOCAL_MACHINE, szFullKey) == ERROR_SUCCESS);
  998. }
  999. BOOL
  1000. SDBAPI
  1001. SdbRegisterDatabase(
  1002. IN LPCTSTR pszDatabasePath,
  1003. IN DWORD dwDatabaseType
  1004. )
  1005. /*++
  1006. Registers any given database so that it is "known" to our database lookup apis
  1007. Caller must ensure that appcompatflags registry entry exists
  1008. If the function fails -- the caller should try to cleanup the mess using SdbUnregisterDatabase
  1009. --*/
  1010. {
  1011. // first we write the database path
  1012. PSDBDATABASEINFO pDbInfo = NULL;
  1013. BOOL bReturn = FALSE;
  1014. DWORD dwPathLength;
  1015. DWORD dwLength;
  1016. LPTSTR pszFullPath = NULL;
  1017. TCHAR szDatabaseID[64]; // sufficient for guid
  1018. LONG lResult;
  1019. TCHAR szFullKey[512];
  1020. HKEY hKeyInstalledSDB = NULL;
  1021. HKEY hKey = NULL;
  1022. BOOL bExpandSZ = FALSE;
  1023. BOOL bFreeFullPath = FALSE;
  1024. //
  1025. // see if we need to expand some strings...
  1026. //
  1027. if (_tcschr(pszDatabasePath, TEXT('%')) != NULL) {
  1028. bExpandSZ = TRUE;
  1029. dwPathLength = ExpandEnvironmentStrings(pszDatabasePath, NULL, 0);
  1030. if (dwPathLength == 0) {
  1031. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1032. "Failed to expand environment strings for \"%s\" Error 0x%lx\n",
  1033. pszDatabasePath, GetLastError()));
  1034. return FALSE;
  1035. }
  1036. pszFullPath = SdbAlloc(dwPathLength * sizeof(WCHAR));
  1037. if (pszFullPath == NULL) {
  1038. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1039. "Failed to allocate 0x%lx bytes for the path buffer \"%s\"\n",
  1040. dwPathLength, pszDatabasePath));
  1041. return FALSE;
  1042. }
  1043. bFreeFullPath = TRUE;
  1044. dwLength = ExpandEnvironmentStrings(pszDatabasePath, pszFullPath, dwPathLength);
  1045. if (dwLength == 0 || dwLength > dwPathLength) {
  1046. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1047. "Failed to expand environment strings for \"%s\" Length 0x%lx Return value 0x%lx Error 0x%lx\n",
  1048. pszDatabasePath, dwPathLength, dwLength, GetLastError()));
  1049. goto HandleError;
  1050. }
  1051. } else { // this path does not need expansion
  1052. pszFullPath = (LPTSTR)pszDatabasePath;
  1053. }
  1054. if (!SdbGetDatabaseInformationByName(pszFullPath, &pDbInfo)) {
  1055. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1056. "Cannot obtain database information for \"%s\"\n", pszFullPath));
  1057. goto HandleError;
  1058. }
  1059. if (!(pDbInfo->dwFlags & DBINFO_GUID_VALID)) {
  1060. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1061. "Cannot register database with no id \"%s\"\n", pszDatabasePath));
  1062. goto HandleError;
  1063. }
  1064. //
  1065. // convert the guid into the string, returns true always
  1066. //
  1067. SdbGUIDToString(&pDbInfo->guidDB, szDatabaseID);
  1068. //
  1069. // now that we have database information - create entry
  1070. //
  1071. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1072. APPCOMPAT_KEY_PATH_INSTALLEDSDB,
  1073. 0,
  1074. NULL,
  1075. REG_OPTION_NON_VOLATILE,
  1076. KEY_WRITE|KEY_READ,
  1077. NULL,
  1078. &hKeyInstalledSDB,
  1079. NULL);
  1080. if (lResult != ERROR_SUCCESS) {
  1081. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1082. "Failed to create key \"%s\" error 0x%lx\n", APPCOMPAT_KEY_PATH_INSTALLEDSDB, lResult));
  1083. goto HandleError;
  1084. }
  1085. assert(hKeyInstalledSDB != NULL);
  1086. //
  1087. // now create the key for the existing database
  1088. //
  1089. lResult = RegCreateKeyEx(hKeyInstalledSDB, // subkey
  1090. szDatabaseID,
  1091. 0,
  1092. NULL,
  1093. REG_OPTION_NON_VOLATILE,
  1094. KEY_WRITE|KEY_READ,
  1095. NULL,
  1096. &hKey,
  1097. NULL);
  1098. if (lResult != ERROR_SUCCESS) {
  1099. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1100. "Failed to create key \"%s\" error 0x%lx\n", szDatabaseID, lResult));
  1101. goto HandleError;
  1102. }
  1103. assert(hKey != NULL);
  1104. //
  1105. // set values for this database
  1106. //
  1107. lResult = RegSetValueEx(hKey,
  1108. g_szDatabasePath,
  1109. 0,
  1110. bExpandSZ ? REG_EXPAND_SZ : REG_SZ,
  1111. (PBYTE)pszFullPath,
  1112. (_tcslen(pszFullPath) + 1) * sizeof(*pszFullPath));
  1113. if (lResult != ERROR_SUCCESS) {
  1114. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1115. "Failed to set value \"%s\" to \"%s\" Error 0x%lx\n",
  1116. g_szDatabasePath, pszFullPath, lResult));
  1117. goto HandleError;
  1118. }
  1119. lResult = RegSetValueEx(hKey,
  1120. g_szDatabaseType,
  1121. 0,
  1122. REG_DWORD,
  1123. (PBYTE)&dwDatabaseType,
  1124. sizeof(dwDatabaseType));
  1125. if (lResult != ERROR_SUCCESS) {
  1126. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1127. "Failed to set value \"%s\" to 0x%lx Error 0x%lx\n",
  1128. g_szDatabaseType, dwDatabaseType, lResult));
  1129. goto HandleError;
  1130. }
  1131. if (pDbInfo->pszDescription != NULL) {
  1132. lResult = RegSetValueEx(hKey,
  1133. g_szDatabaseDescription,
  1134. 0,
  1135. REG_SZ,
  1136. (PBYTE)pDbInfo->pszDescription,
  1137. (_tcslen(pDbInfo->pszDescription) + 1) * sizeof(*pDbInfo->pszDescription));
  1138. if (lResult != ERROR_SUCCESS) {
  1139. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1140. "Failed to set value \"%s\" to 0x%lx Error 0x%lx\n",
  1141. g_szDatabaseDescription, pDbInfo->pszDescription, lResult));
  1142. goto HandleError;
  1143. }
  1144. }
  1145. bReturn = TRUE;
  1146. HandleError:
  1147. if (hKeyInstalledSDB != NULL) {
  1148. RegCloseKey(hKeyInstalledSDB);
  1149. }
  1150. if (hKey != NULL) {
  1151. RegCloseKey(hKey);
  1152. }
  1153. if (pDbInfo != NULL) {
  1154. SdbFreeDatabaseInformation(pDbInfo);
  1155. }
  1156. if (bFreeFullPath && pszFullPath != NULL) {
  1157. SdbFree(pszFullPath);
  1158. }
  1159. return bReturn;
  1160. }
  1161. DWORD
  1162. SDBAPI
  1163. SdbResolveDatabase(
  1164. IN GUID* pguidDB, // pointer to the database guid to resolve
  1165. OUT LPDWORD lpdwDatabaseType, // optional pointer to the database type
  1166. OUT LPTSTR pszDatabasePath, // optional pointer to the database path
  1167. IN DWORD dwBufferSize // size of the buffer pszDatabasePath in tchars
  1168. )
  1169. {
  1170. TCHAR szDatabaseID[64];
  1171. TCHAR szDatabasePath[MAX_PATH];
  1172. TCHAR szFullKey[512];
  1173. LONG lResult;
  1174. HKEY hKey = NULL;
  1175. DWORD dwDataType;
  1176. DWORD dwDataSize;
  1177. DWORD dwLength = 0;
  1178. //
  1179. // convert guid to string
  1180. //
  1181. if (!SdbGetDatabaseRegPath(pguidDB, szFullKey, CHARCOUNT(szFullKey))) {
  1182. DBGPRINT((sdlError, "SdbResolveDatabase", "Failed to retrieve database key path\n"));
  1183. goto HandleError;
  1184. }
  1185. //
  1186. // open the key
  1187. //
  1188. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1189. szFullKey,
  1190. 0,
  1191. KEY_READ,
  1192. &hKey);
  1193. if (lResult != ERROR_SUCCESS) {
  1194. DBGPRINT((sdlError, "SdbResolveDatabase",
  1195. "Failed to open key \"%s\" Error 0x%lx\n", szFullKey, lResult));
  1196. goto HandleError; // 0 means error
  1197. }
  1198. dwDataSize = sizeof(szDatabasePath);
  1199. lResult = RegQueryValueEx(hKey,
  1200. g_szDatabasePath,
  1201. NULL,
  1202. &dwDataType,
  1203. (LPBYTE)szDatabasePath,
  1204. &dwDataSize);
  1205. if (lResult != ERROR_SUCCESS) {
  1206. DBGPRINT((sdlError, "SdbResolveDatabase",
  1207. "Failed to query value \"%s\" Error 0x%lx\n", g_szDatabasePath, lResult));
  1208. goto HandleError; // 0 means error
  1209. }
  1210. switch(dwDataType) {
  1211. case REG_SZ:
  1212. // see if we have enough room to copy the string
  1213. //
  1214. if (dwBufferSize * sizeof(TCHAR) < dwDataSize) {
  1215. DBGPRINT((sdlWarning, "SdbResolveDatabase",
  1216. "Insufficient buffer for the database path Required 0x%lx Have 0x%lx\n",
  1217. dwDataSize, dwBufferSize * sizeof(TCHAR)));
  1218. goto HandleError;
  1219. }
  1220. RtlMoveMemory(pszDatabasePath, szDatabasePath, dwDataSize);
  1221. dwLength = dwDataSize / sizeof(TCHAR);
  1222. break;
  1223. case REG_EXPAND_SZ:
  1224. // we have to expand the strings
  1225. dwLength = ExpandEnvironmentStrings(szDatabasePath, pszDatabasePath, dwBufferSize);
  1226. if (dwLength == 0 || dwLength > dwBufferSize) {
  1227. DBGPRINT((sdlWarning, "SdbResolveDatabase",
  1228. "Failed to expand output path\n"));
  1229. dwLength = 0;
  1230. goto HandleError;
  1231. }
  1232. break;
  1233. default:
  1234. // can't do it -- fail
  1235. DBGPRINT((sdlError, "SdbResolveDatabase", "Wrong key type 0x%lx\n", dwDataType));
  1236. goto HandleError;
  1237. break;
  1238. }
  1239. if (lpdwDatabaseType != NULL) {
  1240. dwDataSize = sizeof(*lpdwDatabaseType);
  1241. lResult = RegQueryValueEx(hKey,
  1242. g_szDatabaseType,
  1243. NULL,
  1244. &dwDataType,
  1245. (LPBYTE)lpdwDatabaseType,
  1246. &dwDataSize);
  1247. if (lResult == ERROR_SUCCESS) {
  1248. if (dwDataType != REG_DWORD) {
  1249. // bummer, get out -- wrong type
  1250. DBGPRINT((sdlError, "SdbResolveDatabase",
  1251. "Wrong database type - value type 0x%lx\n", dwDataType));
  1252. dwLength = 0;
  1253. goto HandleError;
  1254. }
  1255. } else {
  1256. *lpdwDatabaseType = 0;
  1257. }
  1258. }
  1259. HandleError:
  1260. if (hKey != NULL) {
  1261. RegCloseKey(hKey);
  1262. }
  1263. return dwLength;
  1264. }
  1265. DWORD
  1266. SdbpGetProcessorArchitecture(
  1267. VOID
  1268. )
  1269. {
  1270. SYSTEM_INFO SysInfo;
  1271. SysInfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  1272. GetSystemInfo(&SysInfo);
  1273. return (DWORD)SysInfo.wProcessorArchitecture;
  1274. }
  1275. BOOL
  1276. SdbpIsOs(
  1277. DWORD dwOSSKU
  1278. )
  1279. {
  1280. HKEY hkey;
  1281. DWORD type, cbSize, dwInstalled = 0;
  1282. LONG lRes;
  1283. LPTSTR pszKeyPath;
  1284. BOOL bRet = FALSE;
  1285. if (dwOSSKU == OS_SKU_TAB) {
  1286. pszKeyPath = TABLETPC_KEY_PATH;
  1287. } else if (dwOSSKU == OS_SKU_MED) {
  1288. pszKeyPath = EHOME_KEY_PATH;
  1289. } else {
  1290. DBGPRINT((sdlWarning,
  1291. "SdbpIsOs",
  1292. "Specified unknown OS type 0x%lx",
  1293. dwOSSKU));
  1294. return FALSE;
  1295. }
  1296. lRes = RegOpenKey(HKEY_LOCAL_MACHINE, pszKeyPath, &hkey);
  1297. if (lRes != ERROR_SUCCESS) {
  1298. goto cleanup;
  1299. }
  1300. cbSize = sizeof(DWORD);
  1301. lRes = RegQueryValueEx(hkey, IS_OS_INSTALL_VALUE, NULL, &type, (LPBYTE)&dwInstalled, &cbSize);
  1302. if (lRes != ERROR_SUCCESS || type != REG_DWORD) {
  1303. goto cleanup;
  1304. }
  1305. if (dwInstalled) {
  1306. bRet = TRUE;
  1307. }
  1308. DBGPRINT((sdlInfo|sdlLogPipe,
  1309. "SdbpIsOs",
  1310. "%s %s installed",
  1311. 0,
  1312. (dwOSSKU == OS_SKU_TAB ? TEXT("TabletPC") : TEXT("eHome")),
  1313. (bRet ? TEXT("is") : TEXT("is not"))));
  1314. cleanup:
  1315. RegCloseKey(hkey);
  1316. return bRet;
  1317. }
  1318. VOID
  1319. SdbpGetOSSKU(
  1320. LPDWORD lpdwSKU,
  1321. LPDWORD lpdwSP
  1322. )
  1323. {
  1324. OSVERSIONINFOEXA osv;
  1325. WORD wSuiteMask;
  1326. ZeroMemory(&osv, sizeof(OSVERSIONINFOEXA));
  1327. osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
  1328. GetVersionExA((LPOSVERSIONINFOA)&osv);
  1329. *lpdwSP = 1 << osv.wServicePackMajor;
  1330. wSuiteMask = osv.wSuiteMask;
  1331. if (osv.wProductType == VER_NT_WORKSTATION) {
  1332. if (wSuiteMask & VER_SUITE_PERSONAL) {
  1333. *lpdwSKU = OS_SKU_PER;
  1334. } else {
  1335. #if (_WIN32_WINNT >= 0x0501)
  1336. if (SdbpIsOs(OS_SKU_TAB)) {
  1337. *lpdwSKU = OS_SKU_TAB;
  1338. } else if (SdbpIsOs(OS_SKU_MED)) {
  1339. *lpdwSKU = OS_SKU_MED;
  1340. } else {
  1341. *lpdwSKU = OS_SKU_PRO;
  1342. }
  1343. #else
  1344. *lpdwSKU = OS_SKU_PRO;
  1345. #endif
  1346. }
  1347. return;
  1348. }
  1349. if (wSuiteMask & VER_SUITE_DATACENTER) {
  1350. *lpdwSKU = OS_SKU_DTC;
  1351. return;
  1352. }
  1353. if (wSuiteMask & VER_SUITE_ENTERPRISE) {
  1354. *lpdwSKU = OS_SKU_ADS;
  1355. return;
  1356. }
  1357. if (wSuiteMask & VER_SUITE_BLADE) {
  1358. *lpdwSKU = OS_SKU_BLA;
  1359. return;
  1360. }
  1361. *lpdwSKU = OS_SKU_SRV;
  1362. }