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.

611 lines
16 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1999 **
  4. //*********************************************************************
  5. //
  6. // PID.CPP - Header for the implementation of CProductID
  7. //
  8. // HISTORY:
  9. //
  10. // 1/27/99 a-jaswed Created.
  11. //
  12. #include "pid.h"
  13. #include "appdefs.h"
  14. #include "dispids.h"
  15. #include "msobmain.h"
  16. #include "digpid.h"
  17. #define REG_VAL_PID2 L"PID2"
  18. #define REG_VAL_PID3 L"PID3"
  19. #define REG_VAL_PID3DATA L"PID3Data"
  20. #define REG_VAL_PRODUCTKEY L"ProductKey"
  21. #define SEC_KEY_VER L"Version"
  22. DISPATCHLIST ProductIDExternalInterface[] =
  23. {
  24. {L"get_PID", DISPID_PRODUCTID_GET_PID },
  25. {L"set_PID", DISPID_PRODUCTID_SET_PID },
  26. {L"get_PIDAcceptance", DISPID_PRODUCTID_GET_ACCEPTED },
  27. {L"ValidatePID", DISPID_PRODUCTID_VALIDATEPID }
  28. };
  29. /////////////////////////////////////////////////////////////
  30. // CProductID::CProductID
  31. CProductID::CProductID()
  32. {
  33. WCHAR szKeyName[] = REG_KEY_OOBE_TEMP,
  34. szKeyWindows[] = REG_KEY_WINDOWS,
  35. szPid3[256],
  36. szOemInfoFile[MAX_PATH] = L"\0";
  37. HKEY hKey;
  38. DWORD cb,
  39. dwType;
  40. BOOL bDontCare;
  41. BSTR bstrPid;
  42. // Init member vars
  43. m_cRef = 0;
  44. m_dwPidState = PID_STATE_UNKNOWN;
  45. // Init the data we are going to try to get from the registry.
  46. //
  47. m_szPID2[0] = L'\0';
  48. szPid3[0] = L'\0';
  49. ZeroMemory(&m_abPID3, sizeof(m_abPID3));
  50. if ( RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hKey) == ERROR_SUCCESS )
  51. {
  52. // Get the PID 2 from the registry.
  53. //
  54. cb = sizeof(m_szPID2);
  55. RegQueryValueEx(hKey, REG_VAL_PID2, NULL, &dwType, (LPBYTE) m_szPID2, &cb);
  56. // Get the PID 3 from the registry.
  57. //
  58. cb = sizeof(szPid3);
  59. RegQueryValueEx(hKey, REG_VAL_PID3, NULL, &dwType, (LPBYTE) szPid3, &cb);
  60. // Get the PID 3 data from the registry.
  61. //
  62. cb = sizeof(m_abPID3);
  63. RegQueryValueEx(hKey, REG_VAL_PID3DATA, NULL, &dwType, m_abPID3, &cb);
  64. RegCloseKey(hKey);
  65. }
  66. // If we don't already have a saved state PID3 string, we need to
  67. // try to read it from the places where the OEM can pre-populate it.
  68. //
  69. if ( ( szPid3[0] == L'\0' ) &&
  70. ( RegOpenKey(HKEY_LOCAL_MACHINE, szKeyWindows, &hKey) == ERROR_SUCCESS ) )
  71. {
  72. // First try the registry.
  73. //
  74. cb = sizeof(szPid3);
  75. if ( ( RegQueryValueEx(hKey, REG_VAL_PRODUCTKEY, NULL, &dwType, (LPBYTE) szPid3, &cb) != ERROR_SUCCESS ) ||
  76. ( szPid3[0] == L'\0' ) )
  77. {
  78. // Now try the INI file.
  79. //
  80. GetSystemDirectory(szOemInfoFile, MAX_CHARS_IN_BUFFER(szOemInfoFile));
  81. lstrcat(szOemInfoFile, OEMINFO_INI_FILENAME);
  82. GetPrivateProfileString(SEC_KEY_VER, REG_VAL_PRODUCTKEY, L"\0", szPid3, MAX_CHARS_IN_BUFFER(szPid3), szOemInfoFile);
  83. }
  84. RegCloseKey(hKey);
  85. }
  86. // We need to store the PID we retrieved as a BSTR in the object.
  87. //
  88. m_bstrPID = SysAllocString(szPid3);
  89. // We assume the PID was accepted if we have the PID 2 & 3 strings.
  90. //
  91. if ( m_szPID2[0] && szPid3[0] )
  92. m_dwPidState = PID_STATE_VALID;
  93. else if ( szPid3[0] )
  94. ValidatePID(&bDontCare);
  95. else
  96. m_dwPidState = PID_STATE_INVALID;
  97. // If the PID is invalid, we don't want it.
  98. //
  99. if ( m_dwPidState == PID_STATE_INVALID )
  100. {
  101. bstrPid = SysAllocString(L"\0");
  102. set_PID(bstrPid);
  103. SysFreeString(bstrPid);
  104. }
  105. m_szProdType[0] = L'\0';
  106. }
  107. /////////////////////////////////////////////////////////////
  108. // CProductID::~CProductID
  109. CProductID::~CProductID()
  110. {
  111. SysFreeString(m_bstrPID);
  112. assert(m_cRef == 0);
  113. }
  114. VOID CProductID::SaveState()
  115. {
  116. WCHAR szKeyName[] = REG_KEY_OOBE_TEMP;
  117. HKEY hKey;
  118. LPWSTR lpszPid3;
  119. if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS )
  120. {
  121. // Save the PID 2 to the registry.
  122. //
  123. if ( m_szPID2[0] )
  124. RegSetValueEx(hKey, REG_VAL_PID2, 0, REG_SZ, (LPBYTE) m_szPID2, BYTES_REQUIRED_BY_SZ(m_szPID2));
  125. else
  126. RegDeleteValue(hKey, REG_VAL_PID2);
  127. // Save the PID 3 to the registry.
  128. //
  129. lpszPid3 = m_bstrPID;
  130. if ( *lpszPid3 )
  131. RegSetValueEx(hKey, REG_VAL_PID3, 0, REG_SZ, (LPBYTE) lpszPid3, BYTES_REQUIRED_BY_SZ(lpszPid3));
  132. else
  133. RegDeleteValue(hKey, REG_VAL_PID3);
  134. // Save the PID 3 data from the registry.
  135. //
  136. if ( *((LPDWORD) m_abPID3) )
  137. RegSetValueEx(hKey, REG_VAL_PID3DATA, 0, REG_BINARY, m_abPID3, *((LPDWORD) m_abPID3));
  138. else
  139. RegDeleteValue(hKey, REG_VAL_PID3DATA);
  140. RegFlushKey(hKey);
  141. RegCloseKey(hKey);
  142. }
  143. }
  144. ////////////////////////////////////////////////
  145. ////////////////////////////////////////////////
  146. //// GET / SET :: PID
  147. ////
  148. HRESULT CProductID::set_PID(BSTR bstrVal)
  149. {
  150. LPWSTR lpszNew,
  151. lpszOld;
  152. lpszNew = bstrVal;
  153. lpszOld = m_bstrPID;
  154. // No need to set it if we alread have
  155. // the same string.
  156. //
  157. if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpszNew, -1, lpszOld, -1) != CSTR_EQUAL )
  158. {
  159. m_dwPidState = PID_STATE_UNKNOWN;
  160. SysFreeString(m_bstrPID);
  161. m_bstrPID = SysAllocString(bstrVal);
  162. m_szPID2[0] = L'\0';
  163. ZeroMemory(&m_abPID3, sizeof(m_abPID3));
  164. SaveState();
  165. }
  166. return S_OK;
  167. }
  168. HRESULT CProductID::get_PID(BSTR* pbstrVal)
  169. {
  170. *pbstrVal = SysAllocString(m_bstrPID);
  171. return S_OK;
  172. }
  173. HRESULT CProductID::get_PID2(LPWSTR* lplpszPid2)
  174. {
  175. *lplpszPid2 = SysAllocString(m_szPID2);
  176. return S_OK;
  177. }
  178. HRESULT CProductID::get_PID3Data(LPBYTE* lplpabPid3Data)
  179. {
  180. *lplpabPid3Data = m_abPID3;
  181. return S_OK;
  182. }
  183. HRESULT CProductID::get_PIDAcceptance(BOOL* pbVal)
  184. {
  185. #if 0
  186. *pbVal = (m_dwPidState == PID_STATE_VALID);
  187. #endif // 0
  188. // BUGBUG: get_PIDAcceptance not implemented.
  189. *pbVal = TRUE;
  190. return S_OK;
  191. }
  192. HRESULT CProductID::get_ProductType(LPWSTR* lplpszProductType)
  193. {
  194. // BUGBUG: get_ProductType not implemented
  195. m_szProdType[0] = L'\0';
  196. *lplpszProductType = SysAllocString(m_szProdType);
  197. return S_OK;
  198. }
  199. HRESULT CProductID::ValidatePID(BOOL* pbIsValid)
  200. {
  201. BOOL bValid = FALSE;
  202. LPWSTR lpszPid3;
  203. WCHAR szOemId[5] = L"\0";
  204. DWORD dwSkuFlags = 0;
  205. // Don't need to check if we know it is already valid.
  206. //
  207. if ( m_dwPidState == PID_STATE_VALID )
  208. *pbIsValid = TRUE;
  209. else if ( m_dwPidState == PID_STATE_INVALID )
  210. *pbIsValid = FALSE;
  211. else
  212. {
  213. // Need to convert m_bstrPID to an ANSI string.
  214. //
  215. lpszPid3 = m_bstrPID;
  216. if ( ( lpszPid3 != NULL ) &&
  217. SetupGetProductType( m_szProdType, &dwSkuFlags ) &&
  218. SetupGetSetupInfo( NULL, 0, NULL, 0,
  219. szOemId, sizeof(szOemId), NULL ) )
  220. {
  221. // Validate the PID!
  222. //
  223. bValid = ( SetupPidGen3(
  224. lpszPid3,
  225. dwSkuFlags,
  226. szOemId,
  227. FALSE,
  228. m_szPID2,
  229. m_abPID3,
  230. NULL) == PID_VALID );
  231. }
  232. // Set the return value.
  233. //
  234. if ( *pbIsValid = bValid )
  235. m_dwPidState = PID_STATE_VALID;
  236. else
  237. {
  238. // Make sure we reset the buffers because the PID isn't valid.
  239. //
  240. m_dwPidState = PID_STATE_INVALID;
  241. m_szPID2[0] = L'\0';
  242. ZeroMemory(&m_abPID3, sizeof(m_abPID3));
  243. }
  244. // Make sure we commit the data to the registry.
  245. //
  246. SaveState();
  247. }
  248. return S_OK;
  249. }
  250. /////////////////////////////////////////////////////////////
  251. /////////////////////////////////////////////////////////////
  252. /////////////////////////////////////////////////////////////
  253. /////// IUnknown implementation
  254. ///////
  255. ///////
  256. /////////////////////////////////////////////////////////////
  257. // CProductID::QueryInterface
  258. STDMETHODIMP CProductID::QueryInterface(REFIID riid, LPVOID* ppvObj)
  259. {
  260. // must set out pointer parameters to NULL
  261. *ppvObj = NULL;
  262. if ( riid == IID_IUnknown)
  263. {
  264. AddRef();
  265. *ppvObj = (IUnknown*)this;
  266. return ResultFromScode(S_OK);
  267. }
  268. if (riid == IID_IDispatch)
  269. {
  270. AddRef();
  271. *ppvObj = (IDispatch*)this;
  272. return ResultFromScode(S_OK);
  273. }
  274. // Not a supported interface
  275. return ResultFromScode(E_NOINTERFACE);
  276. }
  277. /////////////////////////////////////////////////////////////
  278. // CProductID::AddRef
  279. STDMETHODIMP_(ULONG) CProductID::AddRef()
  280. {
  281. return ++m_cRef;
  282. }
  283. /////////////////////////////////////////////////////////////
  284. // CProductID::Release
  285. STDMETHODIMP_(ULONG) CProductID::Release()
  286. {
  287. return --m_cRef;
  288. }
  289. /////////////////////////////////////////////////////////////
  290. /////////////////////////////////////////////////////////////
  291. /////////////////////////////////////////////////////////////
  292. /////// IDispatch implementation
  293. ///////
  294. ///////
  295. /////////////////////////////////////////////////////////////
  296. // CProductID::GetTypeInfo
  297. STDMETHODIMP CProductID::GetTypeInfo(UINT, LCID, ITypeInfo**)
  298. {
  299. return E_NOTIMPL;
  300. }
  301. /////////////////////////////////////////////////////////////
  302. // CProductID::GetTypeInfoCount
  303. STDMETHODIMP CProductID::GetTypeInfoCount(UINT* pcInfo)
  304. {
  305. return E_NOTIMPL;
  306. }
  307. /////////////////////////////////////////////////////////////
  308. // CProductID::GetIDsOfNames
  309. STDMETHODIMP CProductID::GetIDsOfNames(REFIID riid,
  310. OLECHAR** rgszNames,
  311. UINT cNames,
  312. LCID lcid,
  313. DISPID* rgDispId)
  314. {
  315. HRESULT hr = DISP_E_UNKNOWNNAME;
  316. rgDispId[0] = DISPID_UNKNOWN;
  317. for (int iX = 0; iX < sizeof(ProductIDExternalInterface)/sizeof(DISPATCHLIST); iX ++)
  318. {
  319. if(lstrcmp(ProductIDExternalInterface[iX].szName, rgszNames[0]) == 0)
  320. {
  321. rgDispId[0] = ProductIDExternalInterface[iX].dwDispID;
  322. hr = NOERROR;
  323. break;
  324. }
  325. }
  326. // Set the disid's for the parameters
  327. if (cNames > 1)
  328. {
  329. // Set a DISPID for function parameters
  330. for (UINT i = 1; i < cNames ; i++)
  331. rgDispId[i] = DISPID_UNKNOWN;
  332. }
  333. return hr;
  334. }
  335. /////////////////////////////////////////////////////////////
  336. // CProductID::Invoke
  337. HRESULT CProductID::Invoke
  338. (
  339. DISPID dispidMember,
  340. REFIID riid,
  341. LCID lcid,
  342. WORD wFlags,
  343. DISPPARAMS* pdispparams,
  344. VARIANT* pvarResult,
  345. EXCEPINFO* pexcepinfo,
  346. UINT* puArgErr
  347. )
  348. {
  349. HRESULT hr = S_OK;
  350. switch(dispidMember)
  351. {
  352. case DISPID_PRODUCTID_GET_PID:
  353. {
  354. TRACE(L"DISPID_PRODUCTID_GET_PID\n");
  355. if(pvarResult)
  356. {
  357. VariantInit(pvarResult);
  358. V_VT(pvarResult) = VT_BSTR;
  359. get_PID(&(pvarResult->bstrVal));
  360. }
  361. break;
  362. }
  363. case DISPID_PRODUCTID_SET_PID:
  364. {
  365. TRACE(L"DISPID_PRODUCTID_SET_PID\n");
  366. if(pdispparams && &pdispparams[0].rgvarg[0])
  367. set_PID(pdispparams[0].rgvarg[0].bstrVal);
  368. break;
  369. }
  370. case DISPID_PRODUCTID_GET_ACCEPTED:
  371. {
  372. TRACE(L"DISPID_PRODUCTID_GET_ACCEPTED\n");
  373. if(pvarResult)
  374. {
  375. VariantInit(pvarResult);
  376. V_VT(pvarResult) = VT_BOOL;
  377. get_PIDAcceptance((BOOL*)&(pvarResult->boolVal));
  378. }
  379. break;
  380. }
  381. case DISPID_PRODUCTID_VALIDATEPID:
  382. {
  383. TRACE(L"DISPID_PRODUCTID_VALIDATEPID\n");
  384. if(pvarResult)
  385. {
  386. VariantInit(pvarResult);
  387. V_VT(pvarResult) = VT_BOOL;
  388. ValidatePID((BOOL*)&(pvarResult->boolVal));
  389. }
  390. break;
  391. }
  392. default:
  393. {
  394. hr = DISP_E_MEMBERNOTFOUND;
  395. break;
  396. }
  397. }
  398. return hr;
  399. }
  400. #ifdef PRERELEASE
  401. BOOL
  402. GetCdKey (
  403. OUT PBYTE CdKey
  404. )
  405. {
  406. DIGITALPID dpid;
  407. DWORD type;
  408. DWORD rc;
  409. HKEY key;
  410. DWORD size = sizeof (dpid);
  411. BOOL b = FALSE;
  412. rc = RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), &key);
  413. if (rc == ERROR_SUCCESS) {
  414. rc = RegQueryValueEx (key, TEXT("DigitalProductId"), NULL, &type, (LPBYTE)&dpid, &size);
  415. if (rc == ERROR_SUCCESS && type == REG_BINARY) {
  416. CopyMemory (CdKey, &dpid.abCdKey, sizeof (dpid.abCdKey));
  417. b = TRUE;
  418. }
  419. else
  420. {
  421. TRACE1(L"OOBE: GetDigitalID, RegQueryValueEx failed, errorcode = %d", rc);
  422. }
  423. RegCloseKey (key);
  424. }
  425. else
  426. {
  427. TRACE1(L"OOBE: GetDigitalID, RegOpenKey failed, errorcode = %d", rc);
  428. }
  429. return b;
  430. }
  431. const unsigned int iBase = 24;
  432. //
  433. // obtained from Jim Harkins 11/27/2000
  434. //
  435. void EncodePid3g(
  436. TCHAR *pchCDKey3Chars, // [OUT] pointer to 29+1 character Secure Product key
  437. LPBYTE pbCDKey3) // [IN] pointer to 15-byte binary Secure Product Key
  438. {
  439. // Given the binary PID 3.0 we need to encode
  440. // it into ASCII characters. We're only allowed to
  441. // use 24 characters so we need to do a base 2 to
  442. // base 24 conversion. It's just like any other
  443. // base conversion execpt the numbers are bigger
  444. // so we have to do the long division ourselves.
  445. const TCHAR achDigits[] = TEXT("BCDFGHJKMPQRTVWXY2346789");
  446. int iCDKey3Chars = 29;
  447. int cGroup = 0;
  448. pchCDKey3Chars[iCDKey3Chars--] = TEXT('\0');
  449. while (0 <= iCDKey3Chars)
  450. {
  451. unsigned int i = 0; // accumulator
  452. int iCDKey3;
  453. for (iCDKey3 = 15-1; 0 <= iCDKey3; --iCDKey3)
  454. {
  455. i = (i * 256) + pbCDKey3[iCDKey3];
  456. pbCDKey3[iCDKey3] = (BYTE)(i / iBase);
  457. i %= iBase;
  458. }
  459. // i now contains the remainder, which is the current digit
  460. pchCDKey3Chars[iCDKey3Chars--] = achDigits[i];
  461. // add '-' between groups of 5 chars
  462. if (++cGroup % 5 == 0 && iCDKey3Chars > 0)
  463. {
  464. pchCDKey3Chars[iCDKey3Chars--] = TEXT('-');
  465. }
  466. }
  467. return;
  468. }
  469. #endif
  470. void CheckDigitalID()
  471. {
  472. #ifdef PRERELEASE
  473. WCHAR WinntPath[MAX_PATH];
  474. BYTE abCdKey[16];
  475. TCHAR ProductId[64] = TEXT("\0"),
  476. szPid[32];
  477. if (GetCdKey (abCdKey))
  478. {
  479. EncodePid3g (ProductId, abCdKey);
  480. // Now compare this value with the productKey value from $winnt$.inf
  481. if(GetCanonicalizedPath(WinntPath, WINNT_INF_FILENAME))
  482. {
  483. if (GetPrivateProfileString(L"UserData",
  484. REG_VAL_PRODUCTKEY,
  485. L"\0",
  486. szPid, MAX_CHARS_IN_BUFFER(szPid),
  487. WinntPath) != 0)
  488. {
  489. if (lstrcmpi(szPid, ProductId) != 0)
  490. {
  491. TRACE1(L"CheckDigitalID: PID in registry and file are different. Registry has: %s",ProductId);
  492. }
  493. else
  494. {
  495. TRACE(L"CheckDigitalID checks out OK");
  496. }
  497. }
  498. else
  499. {
  500. TRACE1(L"CheckDigitalID:Could not get PID from File: %s", WinntPath);
  501. }
  502. }
  503. else
  504. {
  505. TRACE1(L"CheckDigitalID: Could not get path to %s", WINNT_INF_FILENAME);
  506. }
  507. }
  508. #endif
  509. return;
  510. }