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.

563 lines
15 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. PWSTR ArchitectureString;
  106. *pInfEntry = NULL;
  107. if (InfDirectory == NULL) {
  108. return ERROR_NOT_SUPPORTED;
  109. }
  110. //
  111. // we find out what the relative path within the IMIRROR directory is
  112. // for this client's setup files.
  113. //
  114. if ((*InfDirectory != L'\\') ||
  115. (*(InfDirectory+1) != L'\\') ) {
  116. useWholePath:
  117. //
  118. // Make sure there is room for InfDirectory + '\' (1 byte)
  119. // + architecture (MAX_ARCHITECTURE_LENGTH bytes) + '\0' (1 byte).
  120. if (wcslen(InfDirectory) + MAX_ARCHITECTURE_LENGTH + 2 >=
  121. sizeof(SetupPath) / sizeof(SetupPath[0])) {
  122. return ERROR_BAD_PATHNAME;
  123. }
  124. wcscpy( SetupPath, InfDirectory );
  125. } else {
  126. PWCHAR beginRelativePath = InfDirectory + 2; // skip leading slashes
  127. //
  128. // skip computer name
  129. //
  130. while ((*beginRelativePath != L'\0') &&
  131. (*beginRelativePath != L'\\')) {
  132. beginRelativePath++;
  133. }
  134. //
  135. // we should be at the start of the sharename.
  136. //
  137. if (*beginRelativePath != L'\\') {
  138. goto useWholePath;
  139. }
  140. beginRelativePath++;
  141. //
  142. // skip share name
  143. //
  144. while ((*beginRelativePath != L'\0') &&
  145. (*beginRelativePath != L'\\')) {
  146. beginRelativePath++;
  147. }
  148. //
  149. // we should be at the start of the relative directory
  150. //
  151. if (*beginRelativePath != L'\\') {
  152. goto useWholePath;
  153. }
  154. //
  155. // Make sure there is room for IntelliMirrorPathW +
  156. // beginRelativePath + '\' (1 byte) + architecture
  157. // (MAX_ARCHITECTURE_LENGTH bytes) + '\0' (1 byte).
  158. //
  159. if (wcslen(IntelliMirrorPathW) + wcslen(beginRelativePath) + MAX_ARCHITECTURE_LENGTH + 2 >=
  160. sizeof(SetupPath) / sizeof(SetupPath[0])) {
  161. return ERROR_BAD_PATHNAME;
  162. }
  163. wcscpy( SetupPath, IntelliMirrorPathW );
  164. wcscat( SetupPath, beginRelativePath );
  165. }
  166. RtlInitUnicodeString( &infDirString, SetupPath );
  167. RtlUpcaseUnicodeString( &infDirString, &infDirString, FALSE );
  168. // convert the path to uppercase to speed our searches
  169. switch (Architecture) {
  170. #if 0
  171. //
  172. // obsoleted architectures.
  173. //
  174. case PROCESSOR_ARCHITECTURE_ALPHA:
  175. ArchitectureString = L"\\ALPHA";
  176. break;
  177. case PROCESSOR_ARCHITECTURE_ALPHA64:
  178. ArchitectureString = L"\\AXP64";
  179. break;
  180. case PROCESSOR_ARCHITECTURE_MIPS:
  181. ArchitectureString = L"\\MIPS";
  182. break;
  183. case PROCESSOR_ARCHITECTURE_PPC:
  184. ArchitectureString = L"\\PPC";
  185. break;
  186. #endif
  187. case PROCESSOR_ARCHITECTURE_AMD64:
  188. ArchitectureString = L"\\amd64";
  189. break;
  190. case PROCESSOR_ARCHITECTURE_IA64:
  191. ArchitectureString = L"\\IA64";
  192. break;
  193. case PROCESSOR_ARCHITECTURE_INTEL:
  194. default:
  195. ArchitectureString = L"\\I386";
  196. break;
  197. }
  198. wcscat( SetupPath, ArchitectureString );
  199. RtlInitUnicodeString( &infDirString, SetupPath );
  200. EnterCriticalSection( &NetInfLock );
  201. //
  202. // Find the NETCARD_INF_BLOCK block for this inf directory. If it
  203. // doesn't exist, try to create the block.
  204. //
  205. listEntry = NetInfGlobalInfList.Flink;
  206. while ( listEntry != &NetInfGlobalInfList ) {
  207. pNetCards = (PNETCARD_INF_BLOCK) CONTAINING_RECORD(
  208. listEntry,
  209. NETCARD_INF_BLOCK,
  210. InfBlockEntry );
  211. err = CompareStringW( LOCALE_INVARIANT,
  212. 0,
  213. SetupPath,
  214. infDirString.Length / sizeof(WCHAR),
  215. &pNetCards->InfDirectory[0],
  216. -1
  217. );
  218. if (err == 2) {
  219. break; // a match was found.
  220. }
  221. pNetCards = NULL;
  222. if (err == 3) {
  223. break; // it's greater, add it before listEntry
  224. }
  225. listEntry = listEntry->Flink;
  226. }
  227. if (pNetCards == NULL) {
  228. // we didn't find one. let's create it and parse the INFs.
  229. err = NetInfAllocateNetcardInfo( SetupPath,
  230. Architecture,
  231. &pNetCards );
  232. if (err != ERROR_SUCCESS) {
  233. //
  234. // log an error here that we couldn't get INF file info.
  235. //
  236. PWCHAR strings[2];
  237. strings[0] = SetupPath;
  238. strings[1] = NULL;
  239. BinlReportEventW( ERROR_BINL_ERR_IN_SETUP_PATH,
  240. EVENTLOG_WARNING_TYPE,
  241. 1,
  242. sizeof(ULONG),
  243. strings,
  244. &err
  245. );
  246. BinlAssert( pNetCards == NULL );
  247. LeaveCriticalSection( &NetInfLock );
  248. return err;
  249. }
  250. BinlAssert( pNetCards != NULL );
  251. //
  252. // Now we plop it in the list right in front of listEntry
  253. //
  254. // Either listEntry is equal to the head of the list or
  255. // it's equal to some entry that is larger (sort wise) than the
  256. // inf path passed in. In either case, we can simply insert
  257. // this new entry onto the tail of listEntry.
  258. //
  259. InsertTailList( listEntry, &pNetCards->InfBlockEntry );
  260. EnterCriticalSection( &pNetCards->Lock );
  261. LeaveCriticalSection( &NetInfLock );
  262. //
  263. // Fill in the list with the list of cards to support
  264. //
  265. err = GetNetCardList( pNetCards );
  266. pNetCards->StatusFromScan = err;
  267. if (err != ERROR_SUCCESS) {
  268. PWCHAR strings[2];
  269. LeaveCriticalSection( &pNetCards->Lock );
  270. NetInfCloseNetcardInfo( pNetCards );
  271. DereferenceNetcardInfo( pNetCards );
  272. strings[0] = SetupPath;
  273. strings[1] = NULL;
  274. BinlReportEventW( ERROR_BINL_ERR_IN_SETUP_PATH,
  275. EVENTLOG_WARNING_TYPE,
  276. 1,
  277. sizeof(ULONG),
  278. strings,
  279. &err
  280. );
  281. return err;
  282. }
  283. } else {
  284. BinlAssert( pNetCards->ReferenceCount > 0 );
  285. pNetCards->ReferenceCount++;
  286. LeaveCriticalSection( &NetInfLock );
  287. EnterCriticalSection( &pNetCards->Lock );
  288. err = pNetCards->StatusFromScan;
  289. }
  290. //
  291. // if the thread that is scanning the INFs hits an error, then all threads
  292. // that were waiting on that directory to be scanned should get the same
  293. // error. we use StatusFromScan to hold this.
  294. //
  295. if (err == ERROR_SUCCESS) {
  296. err = FindNetcardInfo( pNetCards, CardInfoVersion, CardIdentity, pInfEntry );
  297. }
  298. LeaveCriticalSection( &pNetCards->Lock );
  299. if ((err == ERROR_SUCCESS) &&
  300. (*pInfEntry != NULL) &&
  301. (FullDriverBuffer != NULL)) {
  302. ULONG sizeToAllocate;
  303. //
  304. // the caller wanted a copy of the fully qualified file name. we
  305. // have all that info here. Allocate what we need plus two, one for
  306. // the null, the other for the backslash.
  307. //
  308. sizeToAllocate = (wcslen( SetupPath ) + 2) * sizeof(WCHAR);
  309. sizeToAllocate += wcslen( (*pInfEntry)->DriverName ) * sizeof(WCHAR);
  310. *FullDriverBuffer = BinlAllocateMemory( sizeToAllocate );
  311. if (*FullDriverBuffer) {
  312. if (_snwprintf( *FullDriverBuffer,
  313. sizeToAllocate/sizeof(WCHAR),
  314. L"%ws\\%ws",
  315. SetupPath,
  316. (*pInfEntry)->DriverName ) < 0) {
  317. BinlFreeMemory( *FullDriverBuffer );
  318. *FullDriverBuffer = NULL;
  319. err = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  320. } else {
  321. *FullDriverBuffer[sizeToAllocate-1] = L'\0';
  322. }
  323. }
  324. }
  325. DereferenceNetcardInfo( pNetCards );
  326. return err;
  327. }
  328. ULONG
  329. NetInfEnumFiles (
  330. PWCHAR FlatDirectory,
  331. ULONG Architecture,
  332. LPVOID Context,
  333. PNETINF_CALLBACK CallBack
  334. )
  335. /*++
  336. Routine Description:
  337. This function searches the drivers we've found and returns a pointer to
  338. an entry that most closely matches the client's request.
  339. Arguments:
  340. FlatDirectory - directory that is target client's setup directory that
  341. contains all INF files for the client's NT installation.
  342. Architecture - PROCESSOR_ARCHITECTURE_XXXXX
  343. CallBack - function to call with names of files
  344. Return Value:
  345. ERROR_SUCCESS, ERROR_NOT_ENOUGH_MEMORY, or ERROR_NOT_SUPPORTED
  346. --*/
  347. {
  348. ULONG err = ERROR_NOT_SUPPORTED; // start off with not found
  349. UNICODE_STRING infDirString;
  350. PNETCARD_INF_BLOCK pNetCards = NULL;
  351. WCHAR SetupPath[MAX_PATH];
  352. //
  353. // this entrypoint can purposely be called from another context than
  354. // BINLSVC. so initialize debugging if that's the case.
  355. //
  356. DebugInitialize();
  357. if (FlatDirectory == NULL) {
  358. err = ERROR_NOT_SUPPORTED;
  359. goto Exit;
  360. }
  361. if (wcslen(FlatDirectory) > MAX_PATH - 1) {
  362. err = ERROR_INVALID_PARAMETER;
  363. goto Exit;
  364. }
  365. wcscpy( SetupPath, FlatDirectory );
  366. RtlInitUnicodeString( &infDirString, SetupPath );
  367. RtlUpcaseUnicodeString( &infDirString, &infDirString, FALSE );
  368. if (StartedNetInfHandler == FALSE) {
  369. err = NetInfStartHandler();
  370. if (err != ERROR_SUCCESS) {
  371. goto Exit;
  372. }
  373. }
  374. err = NetInfAllocateNetcardInfo( SetupPath,
  375. Architecture,
  376. &pNetCards );
  377. if (err != ERROR_SUCCESS) {
  378. goto Exit;
  379. }
  380. BinlAssert( pNetCards != NULL );
  381. pNetCards->FileListCallbackFunction = CallBack;
  382. pNetCards->FileListCallbackContext = Context;
  383. //
  384. // Fill in the list with the list of cards to support
  385. //
  386. err = GetNetCardList( pNetCards );
  387. DereferenceNetcardInfo( pNetCards ); // one for dereference
  388. DereferenceNetcardInfo( pNetCards ); // and one to delete it.
  389. //
  390. // note that we won't bother to call NetInfCloseHandler here because
  391. // we have no idea if the caller on another thread has setup any
  392. // other NETCARD_INF_BLOCKs. So rather than corrupt the list and AV,
  393. // we'll just leak the lock. Not a big deal in RIPREP since it doesn't
  394. // handle more than one. Not an issue for BINL processing INF files.
  395. //
  396. Exit:
  397. //
  398. // this entrypoint can purposely be called from another context than
  399. // BINLSVC. debugging will be uninitialize in process detach when we're
  400. // done.
  401. //
  402. return err;
  403. }
  404. // infdir.c eof