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.

665 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. winres.c
  5. Abstract:
  6. Functions used to read Windows .EXE/.DRV files to obtain the
  7. information contained within their resources.
  8. Environment:
  9. Windows NT Unidrv driver
  10. Revision History:
  11. dd-mm-yy -author-
  12. description
  13. --*/
  14. #include "precomp.h"
  15. HANDLE
  16. HLoadResourceDLL(
  17. WINRESDATA *pWinResData,
  18. PWSTR pwstrResDLL
  19. )
  20. /*++
  21. Routine Description:
  22. This routine loads the resource DLL.
  23. Arguments:
  24. pWinResData Info about Resources
  25. pwstrResDLL Unqualified resource DLL name
  26. Return Value:
  27. Handle to the loaded DLL or NULL for failure
  28. Note:
  29. 10/26/1998 -ganeshp-
  30. Created it.
  31. --*/
  32. {
  33. HANDLE hModule = 0;
  34. PWSTR pwstrQualResDllName = (pWinResData->wchDriverDir);
  35. PWSTR pwstr;
  36. //
  37. // Make sure that resource DLL name is not qualified.
  38. //
  39. if (pwstr = wcsrchr( pwstrResDLL, TEXT('\\')))
  40. pwstrResDLL = pwstr + 1;
  41. //
  42. // Create the fully qualified Name for resource DLL name. We use
  43. // wchDriverDir buffer to create the fully qualified name and reset it.
  44. // Make sure we have enough space.
  45. //
  46. if ( (wcslen(pWinResData->wchDriverDir) + wcslen(pwstrResDLL) + 1) > MAX_PATH )
  47. {
  48. SetLastError(ERROR_INVALID_PARAMETER);
  49. ERR(("HLoadResourceDLL:Length of wchDriverDir + pwstrResDLL longer than MAX_PATH.\n"));
  50. goto ErrorExit;
  51. }
  52. StringCchCatW(pwstrQualResDllName, CCHOF(pWinResData->wchDriverDir), pwstrResDLL);
  53. //
  54. // Now load the resource.
  55. //
  56. #if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  57. //
  58. // For Kernel mode drivers
  59. //
  60. hModule = EngLoadModule(pwstrQualResDllName);
  61. #else
  62. //
  63. // For user mode drivers and UI module.
  64. //
  65. #ifdef WINNT_40 //NT 4.0
  66. hModule = LoadLibraryEx( pwstrQualResDllName, NULL,
  67. DONT_RESOLVE_DLL_REFERENCES );
  68. #else //NT 5.0
  69. hModule = LoadLibrary(pwstrQualResDllName);
  70. #endif
  71. #endif //defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  72. if (hModule == NULL)
  73. {
  74. ERR(("HLoadResourceDLL:Failed to load resource DLL '%ws': Error = %d\n",
  75. pwstrQualResDllName,
  76. GetLastError()));
  77. goto ErrorExit;
  78. }
  79. ErrorExit:
  80. //
  81. // Reset the pWinResData->wchDriverDir. Save a '\0' after last backslash.
  82. //
  83. *(pWinResData->pwstrLastBackSlash + 1) = NUL;
  84. return hModule;
  85. }
  86. BOOL
  87. BInitWinResData(
  88. WINRESDATA *pWinResData,
  89. PWSTR pwstrDriverName,
  90. PUIINFO pUIInfo
  91. )
  92. /*++
  93. Routine Description:
  94. This function opens the resource file name and init the resource table
  95. information and initialize the hModule in WINRESDATA
  96. Arguments:
  97. pWinResData - Pointer to WINRESDATA struct
  98. pwstrDriverName - Fully qualified name of the driver.
  99. pUIInfo - Pointer to UI info.
  100. Return Value:
  101. TRUE if successful, FALSE if there is an error
  102. Note:
  103. --*/
  104. {
  105. PWSTR pstr = NULL;
  106. BOOL bRet = FALSE;
  107. DWORD dwLen;
  108. PWSTR pRootResDLLName;
  109. //
  110. // Always assume we are dealing with NT minidrivers
  111. //
  112. ZeroMemory(pWinResData, sizeof( WINRESDATA ));
  113. //
  114. // Check for fully qualified name. If the driver name is not fully qualified
  115. // then this function will fail.
  116. //
  117. if (pstr = wcsrchr( pwstrDriverName, TEXT('\\')) )
  118. {
  119. //
  120. // wcschr returns pointer to \. We need to add +1 include \ in the
  121. // driver name to be stored.
  122. //
  123. dwLen = (DWORD)((pstr - pwstrDriverName) + 1);
  124. //
  125. // Check if the Length of the driver name is less that MAX_PATH.
  126. //
  127. if ((dwLen + 1) > MAX_PATH)
  128. {
  129. SetLastError(ERROR_INVALID_PARAMETER);
  130. ERR(("BInitWinResData:Invalid pwstrDriverName,longer than MAX_PATH.\n"));
  131. goto ErrorExit;
  132. }
  133. //
  134. // Copy the driver dir name in winresdata. No need to save NULL as
  135. // winresdata is zero initialised.
  136. //
  137. wcsncpy(pWinResData->wchDriverDir,pwstrDriverName, dwLen);
  138. //
  139. // Save the position of the last backslash.
  140. //
  141. pWinResData->pwstrLastBackSlash = pWinResData->wchDriverDir +
  142. wcslen(pWinResData->wchDriverDir) - 1;
  143. }
  144. else // Driver name is not qualified. Error.
  145. {
  146. SetLastError(ERROR_INVALID_PARAMETER);
  147. ERR(("BInitWinResData:Invalid pwstrDriverName,Not qualified.\n"));
  148. goto ErrorExit;
  149. }
  150. //
  151. // Load the root resource DLL
  152. //
  153. pRootResDLLName = OFFSET_TO_POINTER(pUIInfo->pubResourceData,
  154. pUIInfo->loResourceName);
  155. if (pRootResDLLName == NULL)
  156. {
  157. //
  158. // This is OK since the GPD is not required to have the *ResourceDLL entry
  159. //
  160. // Already did ZeroMemory(pWinResData), no need to set hResDLLModule NULL here.
  161. //
  162. VERBOSE(("BInitWinResData: pRootResDLLName is NULL.\n"));
  163. goto OKExit;
  164. }
  165. pWinResData->hResDLLModule = HLoadResourceDLL(pWinResData, pRootResDLLName);
  166. //
  167. // Check for success
  168. //
  169. if (!pWinResData->hResDLLModule)
  170. {
  171. //
  172. // If GPD does specify *ResourceDLL but we can't load it, we will fail.
  173. //
  174. ERR(("BInitWinResData:Failed to load root resource DLL '%ws': Error = %d\n",
  175. pRootResDLLName,
  176. GetLastError()));
  177. goto ErrorExit;
  178. }
  179. OKExit:
  180. //
  181. // Success so save the UI info in Winresdata.
  182. //
  183. bRet = TRUE;
  184. pWinResData->pUIInfo = pUIInfo;
  185. ErrorExit:
  186. return bRet;
  187. }
  188. PWSTR
  189. PGetResourceDLL(
  190. PUIINFO pUIInfo,
  191. PQUALNAMEEX pResQual
  192. )
  193. /*++
  194. Routine Description:
  195. This routine gets the resouce handle from the handle array. If the DLL is
  196. not loaded then it loads it.
  197. Arguments:
  198. pResQual UI Info pointer
  199. pResQual Pointer to qualified ID structure. It contains the info
  200. about resource dll name and resource ID.
  201. Return Value:
  202. Name of the resource DLL or NULL for failure
  203. Note:
  204. 10/26/1998 -ganeshp-
  205. Created it.
  206. --*/
  207. {
  208. PFEATURE pResFeature;
  209. POPTION pResOption;
  210. PTSTR ptstrResDllName = NULL;
  211. if (pUIInfo)
  212. {
  213. //
  214. // Go to the start of the feature list.
  215. //
  216. pResFeature = PGetIndexedFeature(pUIInfo, 0);
  217. if (pResFeature)
  218. {
  219. //
  220. // Add the feature ID to featuer pointer to get Resource feature.
  221. //
  222. pResFeature += pResQual->bFeatureID;
  223. if (pResOption = (PGetIndexedOption(pUIInfo, pResFeature, pResQual->bOptionID & 0x7f)))
  224. {
  225. ptstrResDllName = OFFSET_TO_POINTER(pUIInfo->pubResourceData,
  226. pResOption->loDisplayName);
  227. if (ptstrResDllName == NULL)
  228. {
  229. SetLastError(ERROR_INVALID_PARAMETER);
  230. ERR(("PGetResourceDLL:Resource DLL name is not specified\n"));
  231. }
  232. }
  233. else
  234. {
  235. SetLastError(ERROR_INVALID_PARAMETER);
  236. ERR(("PGetResourceDLL:NULL resource option.\n"));
  237. }
  238. }
  239. else
  240. {
  241. SetLastError(ERROR_INVALID_PARAMETER);
  242. ERR(("PGetResourceDLL:NULL resource Feature.\n"));
  243. }
  244. }
  245. else
  246. {
  247. SetLastError(ERROR_INVALID_PARAMETER);
  248. ERR(("PGetResourceDLL:NULL pUIInfo.\n"));
  249. }
  250. return ptstrResDllName;
  251. }
  252. HANDLE
  253. HGetModuleHandle(
  254. WINRESDATA *pWinResData,
  255. PQUALNAMEEX pQualifiedID
  256. )
  257. /*++
  258. Routine Description:
  259. This routine gets the resouce handle from the handle array. If the DLL is
  260. not loaded then it loads it.
  261. Arguments:
  262. pWinResData Info about Resources
  263. pQualifiedID Pointer to qualified ID structure. It contains the info
  264. about resource dll name and resource ID.
  265. Return Value:
  266. Handle to the loaded DLL or NULL for failure
  267. Note:
  268. 10/26/1998 -ganeshp-
  269. Created it.
  270. --*/
  271. {
  272. HANDLE hModule = 0 ;
  273. PWSTR pResDLLName;
  274. INT iResDLLID;
  275. //
  276. // Only the low 7 bits of bOptionID are valid. So mask them.
  277. //
  278. iResDLLID = (pQualifiedID->bOptionID & 0x7f);
  279. if (iResDLLID >= MAX_RESOURCE)
  280. {
  281. SetLastError(ERROR_INVALID_PARAMETER);
  282. ERR(("HGetModuleHandle:Res DLL ID (%d) larger than MAX_RESOURCE (%d).\n",
  283. iResDLLID, MAX_RESOURCE));
  284. return 0 ;
  285. }
  286. //
  287. // Check for predefined system paper names.
  288. //
  289. if ((*((PDWORD)pQualifiedID) & 0x7FFFFFFF) == RCID_DMPAPER_SYSTEM_NAME)
  290. {
  291. SetLastError(ERROR_INVALID_PARAMETER);
  292. ERR(("RCID_DMPAPER_SYSTEM_NAME is not a valid qualified resource name.\n"));
  293. return 0 ;
  294. }
  295. //
  296. // Check for the root resource DLL.
  297. //
  298. if (pQualifiedID->bFeatureID == 0 && iResDLLID == 0)
  299. {
  300. hModule = pWinResData->hResDLLModule;
  301. }
  302. else
  303. {
  304. hModule = pWinResData->ahModule[iResDLLID];
  305. //
  306. // The module is not loaded so load it.
  307. //
  308. if (!hModule)
  309. {
  310. //
  311. // Get the resource DLL name form Qualified ID.
  312. //
  313. if (pResDLLName = PGetResourceDLL(pWinResData->pUIInfo,pQualifiedID) )
  314. {
  315. hModule = HLoadResourceDLL(pWinResData,pResDLLName);
  316. //
  317. // If successful loading then save the values in handle array
  318. // and increament the counter.
  319. //
  320. if (hModule)
  321. {
  322. pWinResData->ahModule[iResDLLID] = hModule;
  323. pWinResData->cLoadedEntries++;
  324. }
  325. }
  326. else
  327. {
  328. SetLastError(ERROR_INVALID_PARAMETER);
  329. ERR(("HGetModuleHandle:Can't find Resource DLL name in UIINFO.\n"));
  330. }
  331. }
  332. }
  333. return hModule;
  334. }
  335. BOOL
  336. BGetWinRes(
  337. WINRESDATA *pWinResData,
  338. PQUALNAMEEX pQualifiedID,
  339. INT iType,
  340. RES_ELEM *pRInfo
  341. )
  342. /*++
  343. Routine Description:
  344. Get Windows Resource Data for the caller
  345. Arguments:
  346. pWinResData - Pointer to WINRESDATA struct
  347. iQualifiedName - The fully qualified entry name
  348. iType - Type of resource
  349. pRInfo - Results info
  350. Return Value:
  351. TRUE if successful, FALSE if there is an error
  352. --*/
  353. {
  354. INT iName;
  355. HANDLE hModule;
  356. iName = (INT)pQualifiedID->wResourceID;
  357. if (hModule = HGetModuleHandle(pWinResData, pQualifiedID))
  358. {
  359. //
  360. // Now Find the resource.
  361. //
  362. #if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  363. //
  364. // For Kernel mode drivers
  365. //
  366. pRInfo->pvResData = EngFindResource(
  367. hModule,
  368. iName,
  369. iType,
  370. &pRInfo->iResLen);
  371. #else
  372. //
  373. // For user mode drivers and UI module.
  374. //
  375. {
  376. HRSRC hRes;
  377. HGLOBAL hLoadRes;
  378. if( !(hRes = FindResource( hModule, (LPCTSTR)IntToPtr(iName), (LPCTSTR)IntToPtr(iType))) ||
  379. !(hLoadRes = LoadResource( hModule, hRes )) ||
  380. !(pRInfo->pvResData = LockResource(hLoadRes)) )
  381. return FALSE;
  382. pRInfo->iResLen = SizeofResource( hModule, hRes );
  383. }
  384. #endif //defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  385. return(pRInfo->pvResData != NULL);
  386. }
  387. return FALSE;
  388. }
  389. VOID
  390. VWinResClose(
  391. WINRESDATA *pWinResData
  392. )
  393. /*++
  394. Routine Description:
  395. This function frees the resources allocated with this module. This
  396. includes any memory allocated and the file handle to the driver.
  397. Arguments:
  398. pWinResData - Pointer to WINRESDATA struct
  399. Return Value:
  400. None
  401. --*/
  402. {
  403. //
  404. // Free used resources. Which resources are used has been recorded
  405. // in the Handle array field of the WINRESDATA structure passed in to us.
  406. // First free the root resource DLL and other DLLs.
  407. INT iI;
  408. #if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  409. //
  410. // For Kernel mode drivers
  411. //
  412. if (pWinResData->hResDLLModule)
  413. {
  414. EngFreeModule(pWinResData->hResDLLModule);
  415. }
  416. for (iI = 0; iI < MAX_RESOURCE; iI++)
  417. {
  418. if(pWinResData->ahModule[iI])
  419. EngFreeModule(pWinResData->ahModule[iI]);
  420. }
  421. #else
  422. //
  423. // For user mode drivers and UI module.
  424. //
  425. if (pWinResData->hResDLLModule)
  426. {
  427. FreeLibrary(pWinResData->hResDLLModule);
  428. }
  429. for (iI = 0; iI < MAX_RESOURCE; iI++)
  430. {
  431. if(pWinResData->ahModule[iI])
  432. FreeLibrary(pWinResData->ahModule[iI]);
  433. }
  434. #endif //defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  435. //
  436. // Reinitialize with ZeroFill.
  437. //
  438. ZeroMemory(pWinResData, sizeof( WINRESDATA ));
  439. return;
  440. }
  441. INT
  442. ILoadStringW (
  443. WINRESDATA *pWinResData,
  444. INT iID,
  445. PWSTR wstrBuf,
  446. WORD wBuf
  447. )
  448. /*++
  449. Routine Description:
  450. This function copies the requested resource name into the buffer provided
  451. and return the size of the resource string copied.
  452. Arguments:
  453. pWinResData - Pointer to WINRESDATA struct
  454. iID - Resource ID
  455. wstrBuf - Buffer to receive name
  456. wBuf - Size of the buffer in number of characters
  457. Return Value:
  458. The number of characters of the resource string copied into wstrBuf
  459. --*/
  460. {
  461. //
  462. // The string resources are stored in groups of 16. SO, the
  463. // 4 LSBs of iID select which of the 16(entry name), while the remainder
  464. // select the group.
  465. // Each string resource contains a count byte followed by that
  466. // many bytes of data WITHOUT A NULL. Entries that are missing
  467. // have a 0 count.
  468. //
  469. INT iSize,iResID;
  470. BYTE *pb;
  471. WCHAR *pwch;
  472. RES_ELEM RInfo;
  473. PQUALNAMEEX pQualifiedID;
  474. pQualifiedID = (PQUALNAMEEX)&iID;
  475. iResID = pQualifiedID->wResourceID;
  476. pQualifiedID->wResourceID = (pQualifiedID->wResourceID >> 4) + 1;
  477. //
  478. // Get entry name for resource
  479. //
  480. if( !BGetWinRes( pWinResData, (PQUALNAMEEX)&iID, WINRT_STRING, &RInfo ) ||
  481. wBuf < sizeof( WCHAR ) )
  482. {
  483. return 0;
  484. }
  485. //
  486. // Get the group ID
  487. //
  488. iResID &= 0xf;
  489. //
  490. // wBuf has some limit on sensible sizes. For one, it should be
  491. // a multiple of sizeof( WCHAR ). Secondly, we want to put a 0
  492. // to terminate the string, so add that in now.
  493. //
  494. wBuf-- ;
  495. pwch = RInfo.pvResData;
  496. while( --iResID >= 0 )
  497. pwch += 1 + *pwch;
  498. if( iSize = *pwch )
  499. {
  500. if( iSize > wBuf )
  501. iSize = wBuf;
  502. wstrBuf[ iSize ] = (WCHAR)0;
  503. iSize *= sizeof( WCHAR );
  504. memcpy( wstrBuf, ++pwch, iSize );
  505. }
  506. return (iSize/sizeof( WCHAR ) ); // number of characters written
  507. }