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.

1294 lines
37 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. nettype.c
  5. Abstract:
  6. <abstract>
  7. Author:
  8. Jay Thaler (jthaler) 21 Apr 2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "logmsg.h"
  17. #include <Winnetwk.h>
  18. #define DBG_NETRESOURCES "MappedDrives"
  19. //
  20. // Strings
  21. //
  22. #define S_MAPPEDDRIVES_POOL_NAME "MappedDrives"
  23. #define S_MAPPEDDRIVES_NAME TEXT("MappedDrives")
  24. #define S_CORPNET_NAME TEXT("Net Printers and Drives")
  25. //
  26. // Constants
  27. //
  28. // none
  29. //
  30. // Macros
  31. //
  32. // none
  33. //
  34. // Types
  35. //
  36. typedef struct {
  37. PCTSTR Pattern;
  38. HASHTABLE_ENUM HashData;
  39. } NETRESOURCE_ENUM, *PNETRESOURCE_ENUM;
  40. typedef struct {
  41. DWORD DisplayType;
  42. DWORD Usage;
  43. CHAR Comment[MAX_PATH];
  44. } NETDRIVE_DATAA, *PNETDRIVE_DATAA;
  45. typedef struct {
  46. DWORD DisplayType;
  47. DWORD Usage;
  48. WCHAR Comment[MAX_PATH];
  49. } NETDRIVE_DATAW, *PNETDRIVE_DATAW;
  50. #ifdef UNICODE
  51. #define NETDRIVE_DATA NETDRIVE_DATAW
  52. #define PNETDRIVE_DATA PNETDRIVE_DATAW
  53. #else
  54. #define NETDRIVE_DATA NETDRIVE_DATAA
  55. #define PNETDRIVE_DATA PNETDRIVE_DATAA
  56. #endif
  57. //
  58. // Globals
  59. //
  60. PMHANDLE g_MappedDrivesPool = NULL;
  61. HASHTABLE g_MappedDrivesTable;
  62. HASHTABLE g_DriveCollisionTable;
  63. MIG_OBJECTTYPEID g_MappedDriveTypeId = 0;
  64. GROWBUFFER g_MappedDriveConversionBuff = INIT_GROWBUFFER;
  65. BOOL g_MappedDrivesMigEnabled = FALSE;
  66. DWORD g_AvailableDrives = 0;
  67. MIG_OPERATIONID g_MappedDriveOp;
  68. BOOL g_DelayNetDrivesOp = FALSE;
  69. //
  70. // Macro expansion list
  71. //
  72. // None
  73. //
  74. // Private function prototypes
  75. //
  76. // None
  77. //
  78. // Macro expansion definition
  79. //
  80. // None
  81. //
  82. // Private prototypes
  83. //
  84. SGMENUMERATIONCALLBACK SgmMappedDrivesCallback;
  85. VCMENUMERATIONCALLBACK VcmMappedDrivesCallback;
  86. TYPE_ENUMFIRSTPHYSICALOBJECT EnumFirstMappedDrive;
  87. TYPE_ENUMNEXTPHYSICALOBJECT EnumNextMappedDrive;
  88. TYPE_ABORTENUMPHYSICALOBJECT AbortEnumMappedDrive;
  89. TYPE_CONVERTOBJECTTOMULTISZ ConvertMappedDriveToMultiSz;
  90. TYPE_CONVERTMULTISZTOOBJECT ConvertMultiSzToMappedDrive;
  91. TYPE_GETNATIVEOBJECTNAME GetNativeMappedDriveName;
  92. TYPE_ACQUIREPHYSICALOBJECT AcquireMappedDrive;
  93. TYPE_RELEASEPHYSICALOBJECT ReleaseMappedDrive;
  94. TYPE_DOESPHYSICALOBJECTEXIST DoesMappedDriveExist;
  95. TYPE_REMOVEPHYSICALOBJECT RemoveMappedDrive;
  96. TYPE_CREATEPHYSICALOBJECT CreateMappedDrive;
  97. TYPE_REPLACEPHYSICALOBJECT ReplaceMappedDrive;
  98. TYPE_CONVERTOBJECTCONTENTTOUNICODE ConvertMappedDriveContentToUnicode;
  99. TYPE_CONVERTOBJECTCONTENTTOANSI ConvertMappedDriveContentToAnsi;
  100. TYPE_FREECONVERTEDOBJECTCONTENT FreeConvertedMappedDriveContent;
  101. OPMFILTERCALLBACK FilterMappedDrive;
  102. //
  103. // Code
  104. //
  105. BOOL
  106. NetDrivesInitialize (
  107. VOID
  108. )
  109. {
  110. g_MappedDrivesTable = HtAllocWithData (sizeof (PNETDRIVE_DATA));
  111. g_MappedDrivesPool = PmCreateNamedPool (S_MAPPEDDRIVES_POOL_NAME);
  112. return (g_MappedDrivesPool != NULL);
  113. }
  114. VOID
  115. NetDrivesTerminate (
  116. VOID
  117. )
  118. {
  119. HASHTABLE_ENUM e;
  120. PNETDRIVE_DATA netdriveData;
  121. GbFree (&g_MappedDriveConversionBuff);
  122. if (g_MappedDrivesTable) {
  123. if (EnumFirstHashTableString (&e, g_MappedDrivesTable)) {
  124. do {
  125. netdriveData = *((PNETDRIVE_DATA *) e.ExtraData);
  126. if (netdriveData) {
  127. PmReleaseMemory (g_MappedDrivesPool, netdriveData);
  128. }
  129. } while (EnumNextHashTableString (&e));
  130. }
  131. HtFree (g_MappedDrivesTable);
  132. g_MappedDrivesTable = NULL;
  133. }
  134. if (g_MappedDrivesPool) {
  135. PmDestroyPool (g_MappedDrivesPool);
  136. g_MappedDrivesPool = NULL;
  137. }
  138. }
  139. BOOL
  140. pLoadMappedDrivesData (
  141. VOID
  142. )
  143. {
  144. DWORD error;
  145. LPNETRESOURCE netBuffer = NULL;
  146. HANDLE netHandle;
  147. DWORD netBufferSize = 16384; // 16K is a good size
  148. DWORD netNumEntries = -1; // enumerate all possible entries
  149. DWORD i;
  150. PNETDRIVE_DATA netDriveData;
  151. MIG_OBJECTSTRINGHANDLE netObject = NULL;
  152. error = WNetOpenEnum (RESOURCE_REMEMBERED, RESOURCETYPE_DISK, 0, netBuffer, &netHandle);
  153. if (error != NO_ERROR) {
  154. return FALSE;
  155. }
  156. netBuffer = PmGetMemory (g_MappedDrivesPool, netBufferSize);
  157. do {
  158. ZeroMemory(netBuffer, netBufferSize);
  159. error = WNetEnumResource (netHandle, &netNumEntries, netBuffer, &netBufferSize);
  160. if (error == ERROR_NO_MORE_ITEMS) {
  161. break;
  162. }
  163. if (error != NO_ERROR) {
  164. PmReleaseMemory (g_MappedDrivesPool, netBuffer);
  165. return FALSE;
  166. }
  167. for (i=0; i<netNumEntries; i++) {
  168. if (netBuffer[i].lpLocalName != NULL) {
  169. netObject = IsmCreateObjectHandle (netBuffer[i].lpLocalName, netBuffer[i].lpRemoteName);
  170. if (netObject) {
  171. netDriveData = (PNETDRIVE_DATA) PmGetMemory (g_MappedDrivesPool, sizeof (NETDRIVE_DATA));
  172. ZeroMemory (netDriveData, sizeof (NETDRIVE_DATA));
  173. netDriveData->DisplayType = netBuffer[i].dwDisplayType;
  174. netDriveData->Usage = netBuffer[i].dwUsage;
  175. if (netBuffer[i].lpComment) {
  176. StringCopyTcharCount (netDriveData->Comment, netBuffer[i].lpComment, MAX_PATH);
  177. }
  178. HtAddStringEx (g_MappedDrivesTable, netObject, &netDriveData, FALSE);
  179. IsmDestroyObjectHandle (netObject);
  180. }
  181. }
  182. }
  183. } while (error != ERROR_NO_MORE_ITEMS);
  184. PmReleaseMemory (g_MappedDrivesPool, netBuffer);
  185. return TRUE;
  186. }
  187. BOOL
  188. WINAPI
  189. NetDrivesEtmInitialize (
  190. IN MIG_PLATFORMTYPEID Platform,
  191. IN PMIG_LOGCALLBACK LogCallback,
  192. IN PVOID Reserved
  193. )
  194. {
  195. TYPE_REGISTER mappedDrivesTypeData;
  196. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  197. pLoadMappedDrivesData ();
  198. ZeroMemory (&mappedDrivesTypeData, sizeof (TYPE_REGISTER));
  199. if (Platform == PLATFORM_SOURCE) {
  200. mappedDrivesTypeData.EnumFirstPhysicalObject = EnumFirstMappedDrive;
  201. mappedDrivesTypeData.EnumNextPhysicalObject = EnumNextMappedDrive;
  202. mappedDrivesTypeData.AbortEnumPhysicalObject = AbortEnumMappedDrive;
  203. mappedDrivesTypeData.ConvertObjectToMultiSz = ConvertMappedDriveToMultiSz;
  204. mappedDrivesTypeData.ConvertMultiSzToObject = ConvertMultiSzToMappedDrive;
  205. mappedDrivesTypeData.GetNativeObjectName = GetNativeMappedDriveName;
  206. mappedDrivesTypeData.AcquirePhysicalObject = AcquireMappedDrive;
  207. mappedDrivesTypeData.ReleasePhysicalObject = ReleaseMappedDrive;
  208. mappedDrivesTypeData.ConvertObjectContentToUnicode = ConvertMappedDriveContentToUnicode;
  209. mappedDrivesTypeData.ConvertObjectContentToAnsi = ConvertMappedDriveContentToAnsi;
  210. mappedDrivesTypeData.FreeConvertedObjectContent = FreeConvertedMappedDriveContent;
  211. g_MappedDriveTypeId = IsmRegisterObjectType (
  212. S_MAPPEDDRIVES_NAME,
  213. TRUE,
  214. FALSE,
  215. &mappedDrivesTypeData
  216. );
  217. } else {
  218. mappedDrivesTypeData.EnumFirstPhysicalObject = EnumFirstMappedDrive;
  219. mappedDrivesTypeData.EnumNextPhysicalObject = EnumNextMappedDrive;
  220. mappedDrivesTypeData.AbortEnumPhysicalObject = AbortEnumMappedDrive;
  221. mappedDrivesTypeData.ConvertObjectToMultiSz = ConvertMappedDriveToMultiSz;
  222. mappedDrivesTypeData.ConvertMultiSzToObject = ConvertMultiSzToMappedDrive;
  223. mappedDrivesTypeData.GetNativeObjectName = GetNativeMappedDriveName;
  224. mappedDrivesTypeData.AcquirePhysicalObject = AcquireMappedDrive;
  225. mappedDrivesTypeData.ReleasePhysicalObject = ReleaseMappedDrive;
  226. mappedDrivesTypeData.DoesPhysicalObjectExist = DoesMappedDriveExist;
  227. mappedDrivesTypeData.RemovePhysicalObject = RemoveMappedDrive;
  228. mappedDrivesTypeData.CreatePhysicalObject = CreateMappedDrive;
  229. mappedDrivesTypeData.ReplacePhysicalObject = ReplaceMappedDrive;
  230. mappedDrivesTypeData.ConvertObjectContentToUnicode = ConvertMappedDriveContentToUnicode;
  231. mappedDrivesTypeData.ConvertObjectContentToAnsi = ConvertMappedDriveContentToAnsi;
  232. mappedDrivesTypeData.FreeConvertedObjectContent = FreeConvertedMappedDriveContent;
  233. g_MappedDriveTypeId = IsmRegisterObjectType (
  234. S_MAPPEDDRIVES_NAME,
  235. TRUE,
  236. FALSE,
  237. &mappedDrivesTypeData
  238. );
  239. }
  240. MYASSERT (g_MappedDriveTypeId);
  241. return TRUE;
  242. }
  243. VOID
  244. WINAPI
  245. NetDrivesEtmNewUserCreated (
  246. IN PCTSTR UserName,
  247. IN PCTSTR DomainName,
  248. IN PCTSTR UserProfileRoot,
  249. IN PSID UserSid
  250. )
  251. {
  252. // a new user was created, the network drives operations need to be delayed
  253. NetDrivesTerminate ();
  254. g_DelayNetDrivesOp = TRUE;
  255. }
  256. BOOL
  257. WINAPI
  258. NetDrivesSgmInitialize (
  259. IN PMIG_LOGCALLBACK LogCallback,
  260. IN PVOID Reserved
  261. )
  262. {
  263. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  264. return TRUE;
  265. }
  266. BOOL
  267. WINAPI
  268. NetDrivesSgmParse (
  269. IN PVOID Reserved
  270. )
  271. {
  272. PCTSTR friendlyName;
  273. friendlyName = GetStringResource (MSG_NET_DRIVES_NAME);
  274. //IsmAddComponentAlias (
  275. // S_MAPPEDDRIVES_NAME,
  276. // MASTERGROUP_SYSTEM,
  277. // friendlyName,
  278. // COMPONENT_NAME,
  279. // FALSE
  280. // );
  281. IsmAddComponentAlias (
  282. S_CORPNET_NAME,
  283. MASTERGROUP_SYSTEM,
  284. friendlyName,
  285. COMPONENT_NAME,
  286. FALSE
  287. );
  288. FreeStringResource (friendlyName);
  289. return TRUE;
  290. }
  291. UINT
  292. SgmMappedDrivesCallback (
  293. IN PCMIG_OBJECTENUMDATA Data,
  294. IN ULONG_PTR CallerArg
  295. )
  296. {
  297. IsmMakeApplyObject (Data->ObjectTypeId, Data->ObjectName);
  298. IsmSetOperationOnObject (Data->ObjectTypeId, Data->ObjectName, g_MappedDriveOp, NULL, NULL);
  299. IsmMakeNonCriticalObject (Data->ObjectTypeId, Data->ObjectName);
  300. return CALLBACK_ENUM_CONTINUE;
  301. }
  302. BOOL
  303. pEnumMappedDriveWorker (
  304. OUT PMIG_TYPEOBJECTENUM EnumPtr,
  305. IN PNETRESOURCE_ENUM MappedDriveEnum
  306. )
  307. {
  308. if (EnumPtr->ObjectNode) {
  309. IsmDestroyObjectString (EnumPtr->ObjectNode);
  310. EnumPtr->ObjectNode = NULL;
  311. }
  312. if (EnumPtr->ObjectLeaf) {
  313. IsmDestroyObjectString (EnumPtr->ObjectLeaf);
  314. EnumPtr->ObjectLeaf = NULL;
  315. }
  316. if (EnumPtr->NativeObjectName) {
  317. PmReleaseMemory (g_MappedDrivesPool, EnumPtr->NativeObjectName);
  318. EnumPtr->NativeObjectName = NULL;
  319. }
  320. do {
  321. EnumPtr->ObjectName = MappedDriveEnum->HashData.String;
  322. if (!ObsPatternMatch (MappedDriveEnum->Pattern, EnumPtr->ObjectName)) {
  323. if (!EnumNextHashTableString (&MappedDriveEnum->HashData)) {
  324. AbortEnumMappedDrive (EnumPtr);
  325. return FALSE;
  326. }
  327. continue;
  328. }
  329. IsmCreateObjectStringsFromHandle (EnumPtr->ObjectName, &EnumPtr->ObjectNode, &EnumPtr->ObjectLeaf);
  330. EnumPtr->NativeObjectName = JoinPathsInPoolEx ((
  331. g_MappedDrivesPool,
  332. EnumPtr->ObjectNode,
  333. TEXT("<=>"),
  334. EnumPtr->ObjectLeaf,
  335. NULL
  336. ));
  337. EnumPtr->Level = 1;
  338. EnumPtr->SubLevel = 0;
  339. EnumPtr->IsLeaf = FALSE;
  340. EnumPtr->IsNode = TRUE;
  341. EnumPtr->Details.DetailsSize = 0;
  342. EnumPtr->Details.DetailsData = NULL;
  343. return TRUE;
  344. } while (TRUE);
  345. }
  346. BOOL
  347. EnumFirstMappedDrive (
  348. IN OUT PMIG_TYPEOBJECTENUM EnumPtr, CALLER_INITIALIZED
  349. IN MIG_OBJECTSTRINGHANDLE Pattern,
  350. IN UINT MaxLevel
  351. )
  352. {
  353. PNETRESOURCE_ENUM netResourceEnum = NULL;
  354. if (!g_MappedDrivesTable) {
  355. AbortEnumMappedDrive (EnumPtr);
  356. return FALSE;
  357. }
  358. netResourceEnum = (PNETRESOURCE_ENUM) PmGetMemory (g_MappedDrivesPool, sizeof (NETRESOURCE_ENUM));
  359. netResourceEnum->Pattern = PmDuplicateString (g_MappedDrivesPool, Pattern);
  360. EnumPtr->EtmHandle = (LONG_PTR) netResourceEnum;
  361. if (EnumFirstHashTableString (&netResourceEnum->HashData, g_MappedDrivesTable)) {
  362. return pEnumMappedDriveWorker (EnumPtr, netResourceEnum);
  363. } else {
  364. AbortEnumMappedDrive (EnumPtr);
  365. return FALSE;
  366. }
  367. }
  368. BOOL
  369. EnumNextMappedDrive (
  370. IN OUT PMIG_TYPEOBJECTENUM EnumPtr
  371. )
  372. {
  373. PNETRESOURCE_ENUM netResourceEnum = NULL;
  374. netResourceEnum = (PNETRESOURCE_ENUM)(EnumPtr->EtmHandle);
  375. if (!netResourceEnum) {
  376. AbortEnumMappedDrive (EnumPtr);
  377. return FALSE;
  378. }
  379. if (EnumNextHashTableString (&netResourceEnum->HashData)) {
  380. return pEnumMappedDriveWorker (EnumPtr, netResourceEnum);
  381. } else {
  382. AbortEnumMappedDrive (EnumPtr);
  383. return FALSE;
  384. }
  385. }
  386. VOID
  387. AbortEnumMappedDrive (
  388. IN OUT PMIG_TYPEOBJECTENUM EnumPtr
  389. )
  390. {
  391. PNETRESOURCE_ENUM netResourceEnum = NULL;
  392. if (EnumPtr->ObjectNode) {
  393. IsmDestroyObjectString (EnumPtr->ObjectNode);
  394. EnumPtr->ObjectNode = NULL;
  395. }
  396. if (EnumPtr->ObjectLeaf) {
  397. IsmDestroyObjectString (EnumPtr->ObjectLeaf);
  398. EnumPtr->ObjectLeaf = NULL;
  399. }
  400. if (EnumPtr->NativeObjectName) {
  401. PmReleaseMemory (g_MappedDrivesPool, EnumPtr->NativeObjectName);
  402. EnumPtr->NativeObjectName = NULL;
  403. }
  404. netResourceEnum = (PNETRESOURCE_ENUM)(EnumPtr->EtmHandle);
  405. if (!netResourceEnum) {
  406. ZeroMemory (EnumPtr, sizeof (MIG_TYPEOBJECTENUM));
  407. return;
  408. }
  409. PmReleaseMemory (g_MappedDrivesPool, netResourceEnum->Pattern);
  410. PmReleaseMemory (g_MappedDrivesPool, netResourceEnum);
  411. ZeroMemory (EnumPtr, sizeof (MIG_TYPEOBJECTENUM));
  412. }
  413. BOOL
  414. AcquireMappedDrive (
  415. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  416. OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED
  417. IN MIG_CONTENTTYPE ContentType,
  418. IN UINT MemoryContentLimit
  419. )
  420. {
  421. BOOL result = FALSE;
  422. PNETDRIVE_DATA netdriveData;
  423. if (!ObjectContent) {
  424. return FALSE;
  425. }
  426. // NOTE: Do not zero ObjectContent; some of its members were already set
  427. if (ContentType == CONTENTTYPE_FILE) {
  428. // nobody should request this as a file
  429. DEBUGMSG ((
  430. DBG_WHOOPS,
  431. "Unexpected acquire request for %s: Can't acquire mapped drives as files",
  432. ObjectName
  433. ));
  434. return FALSE;
  435. }
  436. if (HtFindStringEx (g_MappedDrivesTable, ObjectName, (PVOID) &netdriveData, FALSE)) {
  437. //
  438. // Fill in all the content members. We already zeroed the struct,
  439. // so most of the members are taken care of because they are zero.
  440. //
  441. ObjectContent->MemoryContent.ContentBytes = (PBYTE)netdriveData;
  442. ObjectContent->MemoryContent.ContentSize = sizeof(NETDRIVE_DATA);
  443. result = TRUE;
  444. }
  445. return result;
  446. }
  447. BOOL
  448. ReleaseMappedDrive (
  449. IN OUT PMIG_CONTENT ObjectContent
  450. )
  451. {
  452. if (ObjectContent) {
  453. ZeroMemory (ObjectContent, sizeof (MIG_CONTENT));
  454. }
  455. return TRUE;
  456. }
  457. BOOL
  458. DoesMappedDriveExist (
  459. IN MIG_OBJECTSTRINGHANDLE ObjectName
  460. )
  461. {
  462. if (!g_MappedDrivesTable) {
  463. return FALSE;
  464. }
  465. return (HtFindStringEx (g_MappedDrivesTable, ObjectName, NULL, FALSE) != NULL);
  466. }
  467. BOOL
  468. RemoveMappedDrive (
  469. IN MIG_OBJECTSTRINGHANDLE ObjectName
  470. )
  471. {
  472. PCTSTR node;
  473. PCTSTR leaf;
  474. DWORD result = ERROR_NOT_FOUND;
  475. if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
  476. if (node && (leaf)) {
  477. IsmRecordOperation (JRNOP_DELETE,
  478. g_MappedDriveTypeId,
  479. ObjectName);
  480. // Only set CONNECT_UPDATE_PROFILE when deleting a connection that persists
  481. result = WNetCancelConnection2 ((LPCTSTR)node, CONNECT_UPDATE_PROFILE, TRUE);
  482. if (result != ERROR_SUCCESS) {
  483. DEBUGMSG ((DBG_NETRESOURCES, "Failed to delete existent net resource %s", node));
  484. }
  485. }
  486. IsmDestroyObjectString (node);
  487. IsmDestroyObjectString (leaf);
  488. }
  489. return (result == ERROR_SUCCESS);
  490. }
  491. BOOL
  492. CreateMappedDrive (
  493. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  494. IN PMIG_CONTENT ObjectContent
  495. )
  496. {
  497. PCTSTR node;
  498. PCTSTR leaf;
  499. NETRESOURCE netResource;
  500. BOOL result = ERROR_NOT_FOUND;
  501. PNETDRIVE_DATA netDriveData = NULL;
  502. if (!ObjectContent->ContentInFile) {
  503. if (ObjectContent->MemoryContent.ContentBytes && ObjectContent->MemoryContent.ContentSize) {
  504. if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
  505. if (node && (leaf)) {
  506. if (g_DelayNetDrivesOp) {
  507. // we need to delay this operation
  508. // record delayed printer create operation
  509. IsmRecordDelayedOperation (
  510. JRNOP_CREATE,
  511. g_MappedDriveTypeId,
  512. ObjectName,
  513. ObjectContent
  514. );
  515. result = TRUE;
  516. } else {
  517. netDriveData = (PNETDRIVE_DATA) PmGetMemory (g_MappedDrivesPool, sizeof (NETDRIVE_DATA));
  518. CopyMemory (netDriveData, ObjectContent->MemoryContent.ContentBytes, sizeof (NETDRIVE_DATA));
  519. ZeroMemory (&netResource, sizeof (NETRESOURCE));
  520. netResource.dwScope = RESOURCE_REMEMBERED;
  521. netResource.dwType = RESOURCETYPE_DISK;
  522. netResource.dwDisplayType = netDriveData->DisplayType;
  523. netResource.dwUsage = netDriveData->Usage;
  524. netResource.lpLocalName = (LPTSTR)node;
  525. netResource.lpRemoteName = (LPTSTR)leaf;
  526. netResource.lpComment = netDriveData->Comment;
  527. netResource.lpProvider = NULL; // Let the API determine the provider
  528. IsmRecordOperation (JRNOP_CREATE,
  529. g_MappedDriveTypeId,
  530. ObjectName);
  531. result = WNetAddConnection2 (&netResource, NULL, NULL, CONNECT_UPDATE_PROFILE);
  532. if (result != ERROR_SUCCESS) {
  533. DEBUGMSG ((DBG_NETRESOURCES, "Failed to add net resource for %s", node));
  534. }
  535. PmReleaseMemory (g_MappedDrivesPool, netDriveData);
  536. }
  537. }
  538. }
  539. }
  540. }
  541. SetLastError (result);
  542. return (result == ERROR_SUCCESS);
  543. }
  544. BOOL
  545. ReplaceMappedDrive (
  546. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  547. IN PMIG_CONTENT ObjectContent
  548. )
  549. {
  550. BOOL result = TRUE;
  551. if (g_DelayNetDrivesOp) {
  552. // we need to delay this operation
  553. // record delayed printer replace operation
  554. IsmRecordDelayedOperation (
  555. JRNOP_REPLACE,
  556. g_MappedDriveTypeId,
  557. ObjectName,
  558. ObjectContent
  559. );
  560. result = TRUE;
  561. } else {
  562. // we are going to delete any existing net share with this name,
  563. // and create a new one
  564. if (DoesMappedDriveExist (ObjectName)) {
  565. result = RemoveMappedDrive (ObjectName);
  566. }
  567. if (result) {
  568. result = CreateMappedDrive (ObjectName, ObjectContent);
  569. }
  570. }
  571. return result;
  572. }
  573. PCTSTR
  574. ConvertMappedDriveToMultiSz (
  575. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  576. IN PMIG_CONTENT ObjectContent
  577. )
  578. {
  579. PCTSTR node, leaf;
  580. PTSTR result = NULL;
  581. BOOL bresult = TRUE;
  582. PNETDRIVE_DATA netDriveData;
  583. if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
  584. MYASSERT (leaf);
  585. g_MappedDriveConversionBuff.End = 0;
  586. GbCopyQuotedString (&g_MappedDriveConversionBuff, node);
  587. GbCopyQuotedString (&g_MappedDriveConversionBuff, leaf);
  588. MYASSERT (ObjectContent->Details.DetailsSize == 0);
  589. MYASSERT (!ObjectContent->ContentInFile);
  590. MYASSERT (ObjectContent->MemoryContent.ContentSize = sizeof (NETDRIVE_DATA));
  591. if (ObjectContent->MemoryContent.ContentBytes) {
  592. netDriveData = (PNETDRIVE_DATA)ObjectContent->MemoryContent.ContentBytes;
  593. wsprintf (
  594. (PTSTR) GbGrow (&g_MappedDriveConversionBuff, (sizeof (DWORD) * 2 + 3) * sizeof (TCHAR)),
  595. TEXT("0x%08X"),
  596. netDriveData->DisplayType
  597. );
  598. wsprintf (
  599. (PTSTR) GbGrow (&g_MappedDriveConversionBuff, (sizeof (DWORD) * 2 + 3) * sizeof (TCHAR)),
  600. TEXT("0x%08X"),
  601. netDriveData->Usage
  602. );
  603. GbCopyQuotedString (&g_MappedDriveConversionBuff, netDriveData->Comment);
  604. } else {
  605. bresult = FALSE;
  606. }
  607. if (bresult) {
  608. GbCopyString (&g_MappedDriveConversionBuff, TEXT(""));
  609. result = IsmGetMemory (g_MappedDriveConversionBuff.End);
  610. CopyMemory (result, g_MappedDriveConversionBuff.Buf, g_MappedDriveConversionBuff.End);
  611. }
  612. g_MappedDriveConversionBuff.End = 0;
  613. IsmDestroyObjectString (node);
  614. INVALID_POINTER (node);
  615. IsmDestroyObjectString (leaf);
  616. INVALID_POINTER (leaf);
  617. }
  618. return result;
  619. }
  620. BOOL
  621. ConvertMultiSzToMappedDrive (
  622. IN PCTSTR ObjectMultiSz,
  623. OUT MIG_OBJECTSTRINGHANDLE *ObjectName,
  624. OUT PMIG_CONTENT ObjectContent CALLER_INITIALIZED OPTIONAL
  625. )
  626. {
  627. MULTISZ_ENUM multiSzEnum;
  628. PCTSTR localName = NULL;
  629. PCTSTR remoteName = NULL;
  630. NETDRIVE_DATA netDriveData;
  631. DWORD dummy;
  632. UINT index;
  633. g_MappedDriveConversionBuff.End = 0;
  634. //
  635. // Parse the multi-sz into the net drive content and details.
  636. // The user may have edited the text (and potentially introduced
  637. // errors).
  638. //
  639. ZeroMemory (&netDriveData, sizeof (NETDRIVE_DATA));
  640. if (EnumFirstMultiSz (&multiSzEnum, ObjectMultiSz)) {
  641. index = 0;
  642. do {
  643. if (index == 0) {
  644. localName = multiSzEnum.CurrentString;
  645. }
  646. if (index == 1) {
  647. remoteName = multiSzEnum.CurrentString;
  648. }
  649. if (index == 2) {
  650. _stscanf (multiSzEnum.CurrentString, TEXT("%lx"), &dummy);
  651. netDriveData.DisplayType = dummy;
  652. }
  653. if (index == 3) {
  654. _stscanf (multiSzEnum.CurrentString, TEXT("%lx"), &dummy);
  655. netDriveData.Usage = dummy;
  656. }
  657. if (index == 4) {
  658. if (!StringIMatch (multiSzEnum.CurrentString, TEXT("<empty>"))) {
  659. StringCopyTcharCount (netDriveData.Comment, multiSzEnum.CurrentString, MAX_PATH);
  660. }
  661. }
  662. index++;
  663. } while (EnumNextMultiSz (&multiSzEnum));
  664. }
  665. if (!localName || !remoteName) {
  666. //
  667. // Bogus data, fail
  668. //
  669. return FALSE;
  670. }
  671. //
  672. // Fill in all the members of the content structure.
  673. //
  674. if (ObjectContent) {
  675. ObjectContent->ContentInFile = FALSE;
  676. ObjectContent->MemoryContent.ContentSize = sizeof (NETDRIVE_DATA);
  677. ObjectContent->MemoryContent.ContentBytes = IsmGetMemory (ObjectContent->MemoryContent.ContentSize);
  678. CopyMemory (
  679. (PBYTE)ObjectContent->MemoryContent.ContentBytes,
  680. &netDriveData,
  681. ObjectContent->MemoryContent.ContentSize
  682. );
  683. ObjectContent->Details.DetailsSize = 0;
  684. ObjectContent->Details.DetailsData = NULL;
  685. }
  686. *ObjectName = IsmCreateObjectHandle (localName, remoteName);
  687. return TRUE;
  688. }
  689. PCTSTR
  690. GetNativeMappedDriveName (
  691. IN MIG_OBJECTSTRINGHANDLE ObjectName
  692. )
  693. {
  694. PCTSTR node = NULL, leaf = NULL;
  695. PTSTR leafPtr = NULL, leafBegin = NULL, nodePtr = NULL;
  696. UINT strSize = 0;
  697. PTSTR result = NULL;
  698. if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
  699. if (leaf) {
  700. leafPtr = _tcsrchr (leaf, TEXT('\\'));
  701. if (leafPtr) {
  702. *leafPtr = 0;
  703. leafPtr ++;
  704. }
  705. leafBegin = (PTSTR)leaf;
  706. while (*leafBegin == TEXT('\\')) {
  707. leafBegin ++;
  708. }
  709. }
  710. if (node) {
  711. nodePtr = _tcsrchr (node, TEXT('\\'));
  712. if (nodePtr) {
  713. *nodePtr = 0;
  714. }
  715. }
  716. if (leafPtr) {
  717. if (node) {
  718. strSize = CharCount (leafPtr) + \
  719. CharCount (TEXT(" on \'")) + \
  720. CharCount (leafBegin) + \
  721. CharCount (TEXT("\' (")) + \
  722. CharCount (node) + \
  723. CharCount (TEXT(")")) + \
  724. 1;
  725. result = IsmGetMemory (strSize * sizeof (TCHAR));
  726. _tcscpy (result, leafPtr);
  727. _tcscat (result, TEXT(" on \'"));
  728. _tcscat (result, leafBegin);
  729. _tcscat (result, TEXT("\' ("));
  730. _tcscat (result, node);
  731. _tcscat (result, TEXT(")"));
  732. } else {
  733. strSize = CharCount (leafPtr) + \
  734. CharCount (TEXT(" on \'")) + \
  735. CharCount (leafBegin) + \
  736. CharCount (TEXT("\'")) + \
  737. 1;
  738. result = IsmGetMemory (strSize * sizeof (TCHAR));
  739. _tcscpy (result, leafPtr);
  740. _tcscat (result, TEXT(" on \'"));
  741. _tcscat (result, leafBegin);
  742. _tcscat (result, TEXT("\'"));
  743. }
  744. } else {
  745. if (leafBegin) {
  746. if (node) {
  747. strSize = CharCount (TEXT("\'")) + \
  748. CharCount (leafBegin) + \
  749. CharCount (TEXT("\' (")) + \
  750. CharCount (node) + \
  751. CharCount (TEXT(")")) + \
  752. 1;
  753. result = IsmGetMemory (strSize * sizeof (TCHAR));
  754. _tcscpy (result, TEXT("\'"));
  755. _tcscat (result, leafBegin);
  756. _tcscat (result, TEXT("\' ("));
  757. _tcscat (result, node);
  758. _tcscat (result, TEXT(")"));
  759. } else {
  760. strSize = CharCount (TEXT("\'")) + \
  761. CharCount (leafBegin) + \
  762. CharCount (TEXT("\'")) + \
  763. 1;
  764. _tcscpy (result, TEXT("\'"));
  765. _tcscat (result, leafBegin);
  766. _tcscat (result, TEXT("\'"));
  767. }
  768. } else {
  769. if (node) {
  770. strSize = CharCount (TEXT("(")) + \
  771. CharCount (node) + \
  772. CharCount (TEXT(")")) + \
  773. 1;
  774. result = IsmGetMemory (strSize * sizeof (TCHAR));
  775. _tcscpy (result, TEXT("("));
  776. _tcscat (result, node);
  777. _tcscat (result, TEXT(")"));
  778. }
  779. }
  780. }
  781. IsmDestroyObjectString (node);
  782. IsmDestroyObjectString (leaf);
  783. }
  784. return result;
  785. }
  786. PMIG_CONTENT
  787. ConvertMappedDriveContentToUnicode (
  788. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  789. IN PMIG_CONTENT ObjectContent
  790. )
  791. {
  792. PMIG_CONTENT result = NULL;
  793. if (!ObjectContent) {
  794. return result;
  795. }
  796. if (ObjectContent->ContentInFile) {
  797. return result;
  798. }
  799. result = IsmGetMemory (sizeof (MIG_CONTENT));
  800. if (result) {
  801. CopyMemory (result, ObjectContent, sizeof (MIG_CONTENT));
  802. if ((ObjectContent->MemoryContent.ContentSize != 0) &&
  803. (ObjectContent->MemoryContent.ContentBytes != NULL)
  804. ) {
  805. // convert Mapped Drive content
  806. result->MemoryContent.ContentBytes = IsmGetMemory (sizeof (NETDRIVE_DATAW));
  807. if (result->MemoryContent.ContentBytes) {
  808. ((PNETDRIVE_DATAW)result->MemoryContent.ContentBytes)->DisplayType =
  809. ((PNETDRIVE_DATAA)ObjectContent->MemoryContent.ContentBytes)->DisplayType;
  810. ((PNETDRIVE_DATAW)result->MemoryContent.ContentBytes)->Usage =
  811. ((PNETDRIVE_DATAA)ObjectContent->MemoryContent.ContentBytes)->Usage;
  812. DirectDbcsToUnicodeN (
  813. ((PNETDRIVE_DATAW)result->MemoryContent.ContentBytes)->Comment,
  814. ((PNETDRIVE_DATAA)ObjectContent->MemoryContent.ContentBytes)->Comment,
  815. MAX_PATH
  816. );
  817. result->MemoryContent.ContentSize = sizeof (NETDRIVE_DATAW);
  818. }
  819. }
  820. }
  821. return result;
  822. }
  823. PMIG_CONTENT
  824. ConvertMappedDriveContentToAnsi (
  825. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  826. IN PMIG_CONTENT ObjectContent
  827. )
  828. {
  829. PMIG_CONTENT result = NULL;
  830. if (!ObjectContent) {
  831. return result;
  832. }
  833. if (ObjectContent->ContentInFile) {
  834. return result;
  835. }
  836. result = IsmGetMemory (sizeof (MIG_CONTENT));
  837. if (result) {
  838. CopyMemory (result, ObjectContent, sizeof (MIG_CONTENT));
  839. if ((ObjectContent->MemoryContent.ContentSize != 0) &&
  840. (ObjectContent->MemoryContent.ContentBytes != NULL)
  841. ) {
  842. // convert Mapped Drive content
  843. result->MemoryContent.ContentBytes = IsmGetMemory (sizeof (NETDRIVE_DATAA));
  844. if (result->MemoryContent.ContentBytes) {
  845. ((PNETDRIVE_DATAA)result->MemoryContent.ContentBytes)->DisplayType =
  846. ((PNETDRIVE_DATAW)ObjectContent->MemoryContent.ContentBytes)->DisplayType;
  847. ((PNETDRIVE_DATAA)result->MemoryContent.ContentBytes)->Usage =
  848. ((PNETDRIVE_DATAW)ObjectContent->MemoryContent.ContentBytes)->Usage;
  849. DirectUnicodeToDbcsN (
  850. ((PNETDRIVE_DATAA)result->MemoryContent.ContentBytes)->Comment,
  851. ((PNETDRIVE_DATAW)ObjectContent->MemoryContent.ContentBytes)->Comment,
  852. MAX_PATH
  853. );
  854. result->MemoryContent.ContentSize = sizeof (NETDRIVE_DATAA);
  855. }
  856. }
  857. }
  858. return result;
  859. }
  860. BOOL
  861. FreeConvertedMappedDriveContent (
  862. IN PMIG_CONTENT ObjectContent
  863. )
  864. {
  865. if (!ObjectContent) {
  866. return TRUE;
  867. }
  868. if (ObjectContent->MemoryContent.ContentBytes) {
  869. IsmReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
  870. }
  871. IsmReleaseMemory (ObjectContent);
  872. return TRUE;
  873. }
  874. BOOL
  875. WINAPI
  876. NetDrivesVcmInitialize (
  877. IN PMIG_LOGCALLBACK LogCallback,
  878. IN PVOID Reserved
  879. )
  880. {
  881. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  882. return TRUE;
  883. }
  884. BOOL
  885. WINAPI
  886. NetDrivesVcmParse (
  887. IN PVOID Reserved
  888. )
  889. {
  890. return NetDrivesSgmParse (Reserved);
  891. }
  892. UINT
  893. VcmMappedDrivesCallback (
  894. IN PCMIG_OBJECTENUMDATA Data,
  895. IN ULONG_PTR CallerArg
  896. )
  897. {
  898. IsmMakePersistentObject (Data->ObjectTypeId, Data->ObjectName);
  899. return CALLBACK_ENUM_CONTINUE;
  900. }
  901. BOOL
  902. pCommonNetDrivesQueueEnumeration (
  903. IN BOOL VcmMode
  904. )
  905. {
  906. ENCODEDSTRHANDLE pattern;
  907. if (!IsmIsComponentSelected (S_MAPPEDDRIVES_NAME, 0) &&
  908. !IsmIsComponentSelected (S_CORPNET_NAME, 0)
  909. ) {
  910. g_MappedDrivesMigEnabled = FALSE;
  911. return TRUE;
  912. }
  913. g_MappedDrivesMigEnabled = TRUE;
  914. g_MappedDriveOp = IsmRegisterOperation (S_OPERATION_DRIVEMAP_FIXCONTENT, TRUE);
  915. pattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE);
  916. IsmQueueEnumeration (
  917. g_MappedDriveTypeId,
  918. pattern,
  919. VcmMode ? VcmMappedDrivesCallback : SgmMappedDrivesCallback,
  920. (ULONG_PTR) 0,
  921. S_MAPPEDDRIVES_NAME
  922. );
  923. IsmDestroyObjectHandle (pattern);
  924. return TRUE;
  925. }
  926. BOOL
  927. WINAPI
  928. NetDrivesSgmQueueEnumeration (
  929. IN PVOID Reserved
  930. )
  931. {
  932. return pCommonNetDrivesQueueEnumeration (FALSE);
  933. }
  934. BOOL
  935. WINAPI
  936. NetDrivesVcmQueueEnumeration (
  937. IN PVOID Reserved
  938. )
  939. {
  940. return pCommonNetDrivesQueueEnumeration (TRUE);
  941. }
  942. BOOL
  943. WINAPI
  944. NetDrivesCsmInitialize (
  945. IN PMIG_LOGCALLBACK LogCallback,
  946. IN PVOID Reserved
  947. )
  948. {
  949. g_AvailableDrives = GetLogicalDrives ();
  950. g_DriveCollisionTable = HtAllocWithData (sizeof (TCHAR));
  951. return TRUE;
  952. }
  953. DWORD
  954. pConvertDriveToBit (
  955. PCTSTR driveString
  956. )
  957. {
  958. DWORD bit = 0;
  959. TCHAR driveLetter;
  960. if (driveString && *driveString) {
  961. driveLetter = (TCHAR)_totlower (*driveString);
  962. if (driveLetter >= TEXT('a') && driveLetter <= TEXT('z')) {
  963. bit = 0x1 << (driveLetter - TEXT('a'));
  964. }
  965. }
  966. return bit;
  967. }
  968. BOOL
  969. pReserveAvailableDrive (
  970. TCHAR *driveLetter
  971. )
  972. {
  973. DWORD bit;
  974. BOOL success = FALSE;
  975. // Start at bit 2 so we only map to C: or higher
  976. for (bit = 2; bit < 26; bit++) {
  977. if (!(g_AvailableDrives & (1 << bit))) {
  978. success = TRUE;
  979. g_AvailableDrives |= (1 << bit);
  980. *driveLetter = (TCHAR)(TEXT('a') + bit);
  981. break;
  982. }
  983. }
  984. return success;
  985. }
  986. BOOL
  987. WINAPI
  988. NetDrivesCsmExecute (
  989. VOID
  990. )
  991. {
  992. GROWBUFFER collisions = INIT_GROWBUFFER;
  993. DWORD driveBit;
  994. TCHAR existingPath[MAX_PATH + 1];
  995. MULTISZ_ENUM e;
  996. TCHAR freeDrive;
  997. DWORD bufferSize;
  998. MIG_OBJECTSTRINGHANDLE pattern;
  999. MIG_OBJECT_ENUM objectEnum;
  1000. PCTSTR node;
  1001. PCTSTR leaf;
  1002. DWORD result;
  1003. // First, enumerate all the mapped drives and look for collisions
  1004. pattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE); // *,*
  1005. if (IsmEnumFirstSourceObject (&objectEnum, g_MappedDriveTypeId, pattern)) {
  1006. do {
  1007. IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
  1008. // Leaf is the remote name.
  1009. driveBit = pConvertDriveToBit (node);
  1010. if (g_AvailableDrives & driveBit) {
  1011. // Something is already there. Is it the same thing?
  1012. ZeroMemory (existingPath, MAX_PATH + 1);
  1013. bufferSize = MAX_PATH + 1;
  1014. result = WNetGetConnection (node, existingPath, &bufferSize);
  1015. if (result != NO_ERROR) {
  1016. // this might be a fixed drive
  1017. GbMultiSzAppend (&collisions, node);
  1018. } else {
  1019. if (!StringIMatch (existingPath, leaf)) {
  1020. // Whoops, we have a collision. Save it for later
  1021. GbMultiSzAppend (&collisions, node);
  1022. }
  1023. }
  1024. } else {
  1025. // It's free, so let's reserve it.
  1026. g_AvailableDrives |= driveBit;
  1027. }
  1028. IsmDestroyObjectString (node);
  1029. IsmDestroyObjectString (leaf);
  1030. } while (IsmEnumNextObject (&objectEnum));
  1031. }
  1032. IsmDestroyObjectHandle (pattern);
  1033. INVALID_POINTER (pattern);
  1034. // Enumerate collided mappings and find new destinations
  1035. if (EnumFirstMultiSz (&e, (PCTSTR) collisions.Buf)) {
  1036. do {
  1037. if (pReserveAvailableDrive (&freeDrive)) {
  1038. HtAddStringEx (g_DriveCollisionTable, e.CurrentString, &freeDrive, FALSE);
  1039. }
  1040. } while (EnumNextMultiSz (&e));
  1041. }
  1042. GbFree (&collisions);
  1043. return TRUE;
  1044. }
  1045. BOOL
  1046. WINAPI
  1047. NetDrivesOpmInitialize (
  1048. IN PMIG_LOGCALLBACK LogCallback,
  1049. IN PVOID Reserved
  1050. )
  1051. {
  1052. //
  1053. // Get attribute and operation types
  1054. //
  1055. g_MappedDriveOp = IsmRegisterOperation (S_OPERATION_DRIVEMAP_FIXCONTENT, TRUE);
  1056. //
  1057. // Register operation callbacks
  1058. //
  1059. IsmRegisterOperationFilterCallback (g_MappedDriveOp, FilterMappedDrive, TRUE, TRUE, FALSE);
  1060. return TRUE;
  1061. }
  1062. BOOL
  1063. WINAPI
  1064. FilterMappedDrive (
  1065. IN PCMIG_FILTERINPUT InputData,
  1066. OUT PMIG_FILTEROUTPUT OutputData,
  1067. IN BOOL NoRestoreObject,
  1068. IN PCMIG_BLOB SourceOperationData, OPTIONAL
  1069. IN PCMIG_BLOB DestinationOperationData OPTIONAL
  1070. )
  1071. {
  1072. PTSTR node = NULL;
  1073. PCTSTR leaf = NULL;
  1074. MIG_OBJECTSTRINGHANDLE destHandle;
  1075. TCHAR driveLetter;
  1076. try {
  1077. if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_MappedDriveTypeId) {
  1078. DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterMappedDrive"));
  1079. __leave;
  1080. }
  1081. if (!IsmCreateObjectStringsFromHandle (
  1082. InputData->OriginalObject.ObjectName,
  1083. &node,
  1084. &leaf
  1085. )) {
  1086. __leave;
  1087. }
  1088. MYASSERT (node);
  1089. MYASSERT (leaf);
  1090. if (node) {
  1091. if (HtFindStringEx (g_DriveCollisionTable, node, &driveLetter, FALSE)) {
  1092. node[0] = driveLetter;
  1093. }
  1094. destHandle = IsmCreateObjectHandle (node, leaf);
  1095. if (destHandle) {
  1096. OutputData->NewObject.ObjectName = destHandle;
  1097. }
  1098. }
  1099. }
  1100. __finally {
  1101. IsmDestroyObjectString (node);
  1102. IsmDestroyObjectString (leaf);
  1103. }
  1104. return TRUE;
  1105. }