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.

531 lines
13 KiB

  1. /*
  2. Module Name:
  3. infdir.c
  4. Abstract:
  5. This module implements utility routines to manipulate structures used to
  6. maintain track INF directories. These directories hold INF files that
  7. we put parse and put change notifies on to track updates.
  8. Author:
  9. Andy Herron Apr 08 1998
  10. Revision History:
  11. */
  12. #include "binl.h"
  13. #pragma hdrstop
  14. #include "netinfp.h"
  15. BOOLEAN StartedNetInfHandler = FALSE;
  16. CRITICAL_SECTION NetInfLock;
  17. LIST_ENTRY NetInfGlobalInfList;
  18. ULONG
  19. NetInfStartHandler (
  20. VOID
  21. )
  22. /*++
  23. Routine Description:
  24. This function just dereferences the block for the 'alive' reference.
  25. This may cause it to be deleted.
  26. Arguments:
  27. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  28. the persistant info required for the netcards.
  29. Return Value:
  30. Windows Error.
  31. --*/
  32. {
  33. if (StartedNetInfHandler == FALSE) {
  34. StartedNetInfHandler = TRUE;
  35. InitializeCriticalSection( &NetInfLock );
  36. InitializeListHead(&NetInfGlobalInfList);
  37. }
  38. return ERROR_SUCCESS;
  39. }
  40. ULONG
  41. NetInfCloseHandler (
  42. VOID
  43. )
  44. /*++
  45. Routine Description:
  46. This function just dereferences the block for the 'alive' reference.
  47. This may cause it to be deleted.
  48. Arguments:
  49. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  50. the persistant info required for the netcards.
  51. Return Value:
  52. Windows Error.
  53. --*/
  54. {
  55. if (StartedNetInfHandler) {
  56. EnterCriticalSection( &NetInfLock );
  57. while (IsListEmpty( &NetInfGlobalInfList ) == FALSE) {
  58. PNETCARD_INF_BLOCK pEntry;
  59. PLIST_ENTRY listEntry = RemoveHeadList( &NetInfGlobalInfList );
  60. pEntry = (PNETCARD_INF_BLOCK) CONTAINING_RECORD(
  61. listEntry,
  62. NETCARD_INF_BLOCK,
  63. InfBlockEntry );
  64. NetInfCloseNetcardInfo( pEntry );
  65. }
  66. StartedNetInfHandler = FALSE;
  67. LeaveCriticalSection( &NetInfLock );
  68. DeleteCriticalSection( &NetInfLock );
  69. }
  70. return ERROR_SUCCESS;
  71. }
  72. ULONG
  73. NetInfFindNetcardInfo (
  74. PWCHAR InfDirectory,
  75. ULONG Architecture,
  76. ULONG CardInfoVersion,
  77. NET_CARD_INFO UNALIGNED * CardIdentity,
  78. PWCHAR *FullDriverBuffer OPTIONAL,
  79. PNETCARD_RESPONSE_DATABASE *pInfEntry
  80. )
  81. /*++
  82. Routine Description:
  83. This function searches the drivers we've found and returns a pointer to
  84. an entry that most closely matches the client's request.
  85. Arguments:
  86. InfDirectory - directory that is target client's setup directory that
  87. contains all INF files for the client's NT installation.
  88. Architecture - PROCESSOR_ARCHITECTURE_XXXXX
  89. CardInfoVersion - Version of the structure passed by the client.
  90. CardIdentity - has the values the app is looking for. we try our best to
  91. find one that matches.
  92. FullDriverBuffer - where we put the fully qualified file path specification
  93. for the driver we find, if they want it.
  94. pInfEntry - the entry that was found if successful. NULL if in error.
  95. Return Value:
  96. ERROR_SUCCESS, ERROR_NOT_ENOUGH_MEMORY, or ERROR_NOT_SUPPORTED
  97. --*/
  98. {
  99. ULONG err = ERROR_NOT_SUPPORTED; // start off with not found
  100. LONG result;
  101. PLIST_ENTRY listEntry;
  102. UNICODE_STRING infDirString;
  103. PNETCARD_INF_BLOCK pNetCards = NULL;
  104. WCHAR SetupPath[MAX_PATH];
  105. *pInfEntry = NULL;
  106. if (InfDirectory == NULL) {
  107. return ERROR_NOT_SUPPORTED;
  108. }
  109. //
  110. // we find out what the relative path within the IMIRROR directory is
  111. // for this client's setup files.
  112. //
  113. if ((*InfDirectory != L'\\') ||
  114. (*(InfDirectory+1) != L'\\') ) {
  115. useWholePath:
  116. //
  117. // Make sure there is room for InfDirectory + '\' (1 byte)
  118. // + architecture (MAX_ARCHITECTURE_LENGTH bytes) + '\0' (1 byte).
  119. if (wcslen(InfDirectory) + MAX_ARCHITECTURE_LENGTH + 2 >=
  120. sizeof(SetupPath) / sizeof(SetupPath[0])) {
  121. return ERROR_BAD_PATHNAME;
  122. }
  123. lstrcpyW( SetupPath, InfDirectory );
  124. } else {
  125. PWCHAR beginRelativePath = InfDirectory + 2; // skip leading slashes
  126. //
  127. // skip computer name
  128. //
  129. while ((*beginRelativePath != L'\0') &&
  130. (*beginRelativePath != L'\\')) {
  131. beginRelativePath++;
  132. }
  133. //
  134. // we should be at the start of the sharename.
  135. //
  136. if (*beginRelativePath != L'\\') {
  137. goto useWholePath;
  138. }
  139. beginRelativePath++;
  140. //
  141. // skip share name
  142. //
  143. while ((*beginRelativePath != L'\0') &&
  144. (*beginRelativePath != L'\\')) {
  145. beginRelativePath++;
  146. }
  147. //
  148. // we should be at the start of the relative directory
  149. //
  150. if (*beginRelativePath != L'\\') {
  151. goto useWholePath;
  152. }
  153. //
  154. // Make sure there is room for IntelliMirrorPathW +
  155. // beginRelativePath + '\' (1 byte) + architecture
  156. // (MAX_ARCHITECTURE_LENGTH bytes) + '\0' (1 byte).
  157. //
  158. if (wcslen(IntelliMirrorPathW) + wcslen(beginRelativePath) + MAX_ARCHITECTURE_LENGTH + 2 >=
  159. sizeof(SetupPath) / sizeof(SetupPath[0])) {
  160. return ERROR_BAD_PATHNAME;
  161. }
  162. lstrcpyW( SetupPath, IntelliMirrorPathW );
  163. lstrcatW( SetupPath, beginRelativePath );
  164. }
  165. RtlInitUnicodeString( &infDirString, SetupPath );
  166. RtlUpcaseUnicodeString( &infDirString, &infDirString, FALSE );
  167. // convert the path to uppercase to speed our searches
  168. if (Architecture == PROCESSOR_ARCHITECTURE_ALPHA) {
  169. lstrcatW( SetupPath, L"\\ALPHA" );
  170. } else if (Architecture == PROCESSOR_ARCHITECTURE_ALPHA64) {
  171. lstrcatW( SetupPath, L"\\AXP64" );
  172. } else if (Architecture == PROCESSOR_ARCHITECTURE_IA64) {
  173. lstrcatW( SetupPath, L"\\IA64" );
  174. } else if (Architecture == PROCESSOR_ARCHITECTURE_MIPS) {
  175. lstrcatW( SetupPath, L"\\MIPS" );
  176. } else if (Architecture == PROCESSOR_ARCHITECTURE_PPC) {
  177. lstrcatW( SetupPath, L"\\PPC" );
  178. } else { // if (Architecture == PROCESSOR_ARCHITECTURE_INTEL) {
  179. lstrcatW( SetupPath, L"\\I386" );
  180. }
  181. RtlInitUnicodeString( &infDirString, SetupPath );
  182. EnterCriticalSection( &NetInfLock );
  183. //
  184. // Find the NETCARD_INF_BLOCK block for this inf directory. If it
  185. // doesn't exist, try to create the block.
  186. //
  187. listEntry = NetInfGlobalInfList.Flink;
  188. while ( listEntry != &NetInfGlobalInfList ) {
  189. pNetCards = (PNETCARD_INF_BLOCK) CONTAINING_RECORD(
  190. listEntry,
  191. NETCARD_INF_BLOCK,
  192. InfBlockEntry );
  193. err = CompareStringW( LOCALE_SYSTEM_DEFAULT,
  194. 0,
  195. SetupPath,
  196. infDirString.Length / sizeof(WCHAR),
  197. &pNetCards->InfDirectory[0],
  198. -1
  199. );
  200. if (err == 2) {
  201. break; // a match was found.
  202. }
  203. pNetCards = NULL;
  204. if (err == 3) {
  205. break; // it's greater, add it before listEntry
  206. }
  207. listEntry = listEntry->Flink;
  208. }
  209. if (pNetCards == NULL) {
  210. // we didn't find one. let's create it and parse the INFs.
  211. err = NetInfAllocateNetcardInfo( SetupPath,
  212. Architecture,
  213. &pNetCards );
  214. if (err != ERROR_SUCCESS) {
  215. //
  216. // log an error here that we couldn't get INF file info.
  217. //
  218. PWCHAR strings[2];
  219. strings[0] = SetupPath;
  220. strings[1] = NULL;
  221. BinlReportEventW( ERROR_BINL_ERR_IN_SETUP_PATH,
  222. EVENTLOG_WARNING_TYPE,
  223. 1,
  224. sizeof(ULONG),
  225. strings,
  226. &err
  227. );
  228. BinlAssert( pNetCards == NULL );
  229. LeaveCriticalSection( &NetInfLock );
  230. return err;
  231. }
  232. BinlAssert( pNetCards != NULL );
  233. //
  234. // Now we plop it in the list right in front of listEntry
  235. //
  236. // Either listEntry is equal to the head of the list or
  237. // it's equal to some entry that is larger (sort wise) than the
  238. // inf path passed in. In either case, we can simply insert
  239. // this new entry onto the tail of listEntry.
  240. //
  241. InsertTailList( listEntry, &pNetCards->InfBlockEntry );
  242. EnterCriticalSection( &pNetCards->Lock );
  243. LeaveCriticalSection( &NetInfLock );
  244. //
  245. // Fill in the list with the list of cards to support
  246. //
  247. err = GetNetCardList( pNetCards );
  248. pNetCards->StatusFromScan = err;
  249. if (err != ERROR_SUCCESS) {
  250. PWCHAR strings[2];
  251. LeaveCriticalSection( &pNetCards->Lock );
  252. NetInfCloseNetcardInfo( pNetCards );
  253. DereferenceNetcardInfo( pNetCards );
  254. strings[0] = SetupPath;
  255. strings[1] = NULL;
  256. BinlReportEventW( ERROR_BINL_ERR_IN_SETUP_PATH,
  257. EVENTLOG_WARNING_TYPE,
  258. 1,
  259. sizeof(ULONG),
  260. strings,
  261. &err
  262. );
  263. return err;
  264. }
  265. } else {
  266. BinlAssert( pNetCards->ReferenceCount > 0 );
  267. pNetCards->ReferenceCount++;
  268. LeaveCriticalSection( &NetInfLock );
  269. EnterCriticalSection( &pNetCards->Lock );
  270. err = pNetCards->StatusFromScan;
  271. }
  272. //
  273. // if the thread that is scanning the INFs hits an error, then all threads
  274. // that were waiting on that directory to be scanned should get the same
  275. // error. we use StatusFromScan to hold this.
  276. //
  277. if (err == ERROR_SUCCESS) {
  278. err = FindNetcardInfo( pNetCards, CardInfoVersion, CardIdentity, pInfEntry );
  279. }
  280. LeaveCriticalSection( &pNetCards->Lock );
  281. if ((err == ERROR_SUCCESS) &&
  282. (*pInfEntry != NULL) &&
  283. (FullDriverBuffer != NULL)) {
  284. ULONG sizeToAllocate;
  285. //
  286. // the caller wanted a copy of the fully qualified file name. we
  287. // have all that info here. Allocate what we need plus two, one for
  288. // the null, the other for the backslash.
  289. //
  290. sizeToAllocate = (lstrlenW( SetupPath ) + 2) * sizeof(WCHAR);
  291. sizeToAllocate += lstrlenW( (*pInfEntry)->DriverName ) * sizeof(WCHAR);
  292. *FullDriverBuffer = BinlAllocateMemory( sizeToAllocate );
  293. if (*FullDriverBuffer) {
  294. lstrcpyW( *FullDriverBuffer, SetupPath );
  295. lstrcatW( *FullDriverBuffer, L"\\" );
  296. lstrcatW( *FullDriverBuffer, (*pInfEntry)->DriverName );
  297. }
  298. }
  299. DereferenceNetcardInfo( pNetCards );
  300. return err;
  301. }
  302. ULONG
  303. NetInfEnumFiles (
  304. PWCHAR FlatDirectory,
  305. ULONG Architecture,
  306. LPVOID Context,
  307. PNETINF_CALLBACK CallBack
  308. )
  309. /*++
  310. Routine Description:
  311. This function searches the drivers we've found and returns a pointer to
  312. an entry that most closely matches the client's request.
  313. Arguments:
  314. FlatDirectory - directory that is target client's setup directory that
  315. contains all INF files for the client's NT installation.
  316. Architecture - PROCESSOR_ARCHITECTURE_XXXXX
  317. CallBack - function to call with names of files
  318. Return Value:
  319. ERROR_SUCCESS, ERROR_NOT_ENOUGH_MEMORY, or ERROR_NOT_SUPPORTED
  320. --*/
  321. {
  322. ULONG err = ERROR_NOT_SUPPORTED; // start off with not found
  323. UNICODE_STRING infDirString;
  324. PNETCARD_INF_BLOCK pNetCards = NULL;
  325. WCHAR SetupPath[MAX_PATH];
  326. if (FlatDirectory == NULL) {
  327. return ERROR_NOT_SUPPORTED;
  328. }
  329. if (lstrlenW(FlatDirectory) > MAX_PATH - 1) {
  330. return ERROR_INVALID_PARAMETER;
  331. }
  332. lstrcpyW( SetupPath, FlatDirectory );
  333. RtlInitUnicodeString( &infDirString, SetupPath );
  334. RtlUpcaseUnicodeString( &infDirString, &infDirString, FALSE );
  335. if (StartedNetInfHandler == FALSE) {
  336. err = NetInfStartHandler();
  337. if (err != ERROR_SUCCESS) {
  338. return err;
  339. }
  340. }
  341. err = NetInfAllocateNetcardInfo( SetupPath,
  342. Architecture,
  343. &pNetCards );
  344. if (err != ERROR_SUCCESS) {
  345. return err;
  346. }
  347. BinlAssert( pNetCards != NULL );
  348. pNetCards->FileListCallbackFunction = CallBack;
  349. pNetCards->FileListCallbackContext = Context;
  350. //
  351. // Fill in the list with the list of cards to support
  352. //
  353. err = GetNetCardList( pNetCards );
  354. DereferenceNetcardInfo( pNetCards ); // one for dereference
  355. DereferenceNetcardInfo( pNetCards ); // and one to delete it.
  356. //
  357. // note that we won't bother to call NetInfCloseHandler here because
  358. // we have no idea if the caller on another thread has setup any
  359. // other NETCARD_INF_BLOCKs. So rather than corrupt the list and AV,
  360. // we'll just leak the lock. Not a big deal in RIPREP since it doesn't
  361. // handle more than one. Not an issue for BINL processing INF files.
  362. //
  363. return err;
  364. }
  365. // infdir.c eof