ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ldevobj.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:        See COPYING in the top level directory
00003  * PROJECT:          ReactOS Win32k subsystem
00004  * PURPOSE:          Support for logical devices
00005  * FILE:             subsystems/win32/win32k/eng/ldevobj.c
00006  * PROGRAMER:        Timo Kreuzer (timo.kreuzer@reactos.org)
00007  */
00008 
00009 #include <win32k.h>
00010 #define NDEBUG
00011 #include <debug.h>
00012 
00013 #ifndef RVA_TO_ADDR
00014 #define RVA_TO_ADDR(Base,Rva) ((PVOID)(((ULONG_PTR)(Base)) + (Rva)))
00015 #endif
00016 
00019 HSEMAPHORE ghsemLDEVList;
00020 LDEVOBJ *gpldevHead = NULL;
00021 LDEVOBJ *gpldevWin32k = NULL;
00022 
00023 
00026 INIT_FUNCTION
00027 NTSTATUS
00028 NTAPI
00029 InitLDEVImpl()
00030 {
00031     ULONG cbSize;
00032 
00033     /* Initialize the loader lock */
00034     ghsemLDEVList = EngCreateSemaphore();
00035     if (!ghsemLDEVList)
00036     {
00037         return STATUS_INSUFFICIENT_RESOURCES;
00038     }
00039 
00040     /* Allocate a LDEVOBJ for win32k */
00041     gpldevWin32k = ExAllocatePoolWithTag(PagedPool,
00042                                          sizeof(LDEVOBJ) +
00043                                          sizeof(SYSTEM_GDI_DRIVER_INFORMATION),
00044                                          GDITAG_LDEV);
00045     if (!gpldevWin32k)
00046     {
00047         return STATUS_NO_MEMORY;
00048     }
00049 
00050     /* Initialize the LDEVOBJ for win32k */
00051     gpldevWin32k->pldevNext = NULL;
00052     gpldevWin32k->pldevPrev = NULL;
00053     gpldevWin32k->ldevtype = LDEV_DEVICE_DISPLAY;
00054     gpldevWin32k->cRefs = 1;
00055     gpldevWin32k->ulDriverVersion = GDI_ENGINE_VERSION;
00056     gpldevWin32k->pGdiDriverInfo = (PVOID)(gpldevWin32k + 1);
00057     RtlInitUnicodeString(&gpldevWin32k->pGdiDriverInfo->DriverName,
00058                          L"\\SystemRoot\\System32\\win32k.sys");
00059     gpldevWin32k->pGdiDriverInfo->ImageAddress = &__ImageBase;
00060     gpldevWin32k->pGdiDriverInfo->SectionPointer = NULL;
00061     gpldevWin32k->pGdiDriverInfo->EntryPoint = (PVOID)DriverEntry;
00062     gpldevWin32k->pGdiDriverInfo->ExportSectionPointer =
00063         RtlImageDirectoryEntryToData(&__ImageBase,
00064                                      TRUE,
00065                                      IMAGE_DIRECTORY_ENTRY_EXPORT,
00066                                      &cbSize);
00067     gpldevWin32k->pGdiDriverInfo->ImageLength = 0; // FIXME
00068 
00069     return STATUS_SUCCESS;
00070 }
00071 
00072 PLDEVOBJ
00073 NTAPI
00074 LDEVOBJ_AllocLDEV(LDEVTYPE ldevtype)
00075 {
00076     PLDEVOBJ pldev;
00077 
00078     /* Allocate the structure from paged pool */
00079     pldev = ExAllocatePoolWithTag(PagedPool, sizeof(LDEVOBJ), GDITAG_LDEV);
00080     if (!pldev)
00081     {
00082         DPRINT1("Failed to allocate LDEVOBJ.\n");
00083         return NULL;
00084     }
00085 
00086     /* Zero out the structure */
00087     RtlZeroMemory(pldev, sizeof(LDEVOBJ));
00088 
00089     /* Set the ldevtype */
00090     pldev->ldevtype = ldevtype;
00091 
00092     return pldev;
00093 }
00094 
00095 VOID
00096 NTAPI
00097 LDEVOBJ_vFreeLDEV(PLDEVOBJ pldev)
00098 {
00099     /* Make sure we don't have a driver loaded */
00100     ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
00101     ASSERT(pldev->cRefs == 0);
00102 
00103     /* Free the memory */
00104     ExFreePoolWithTag(pldev, GDITAG_LDEV);
00105 }
00106 
00107 PDEVMODEINFO
00108 NTAPI
00109 LDEVOBJ_pdmiGetModes(
00110     PLDEVOBJ pldev,
00111     HANDLE hDriver)
00112 {
00113     ULONG cbSize, cbFull;
00114     PDEVMODEINFO pdminfo;
00115 
00116     DPRINT("LDEVOBJ_pdmiGetModes(%p, %p)\n", pldev, hDriver);
00117 
00118     /* Call the driver to get the required size */
00119     cbSize = pldev->pfn.GetModes(hDriver, 0, NULL);
00120     if (!cbSize)
00121     {
00122         DPRINT1("DrvGetModes returned 0\n");
00123         return NULL;
00124     }
00125 
00126     /* Add space for the header */
00127     cbFull = cbSize + FIELD_OFFSET(DEVMODEINFO, adevmode);
00128 
00129     /* Allocate a buffer for the DEVMODE array */
00130     pdminfo = ExAllocatePoolWithTag(PagedPool, cbFull, GDITAG_DEVMODE);
00131     if (!pdminfo)
00132     {
00133         DPRINT1("Could not allocate devmodeinfo\n");
00134         return NULL;
00135     }
00136 
00137     pdminfo->pldev = pldev;
00138     pdminfo->cbdevmode = cbSize;
00139 
00140     /* Call the driver again to fill the buffer */
00141     cbSize = pldev->pfn.GetModes(hDriver, cbSize, pdminfo->adevmode);
00142     if (!cbSize)
00143     {
00144         /* Could not get modes */
00145         DPRINT1("returned size %ld(%ld)\n", cbSize, pdminfo->cbdevmode);
00146         ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE);
00147         pdminfo = NULL;
00148     }
00149 
00150     return pdminfo;
00151 }
00152 
00153 
00154 BOOL
00155 NTAPI
00156 LDEVOBJ_bLoadImage(
00157     IN PLDEVOBJ pldev,
00158     PUNICODE_STRING pstrPathName)
00159 {
00160     PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo;
00161     NTSTATUS Status;
00162     ULONG cbSize;
00163 
00164     /* Make sure no image is loaded yet */
00165     ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
00166 
00167     /* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */
00168     cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pstrPathName->Length;
00169     pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV);
00170     if (!pDriverInfo)
00171     {
00172         DPRINT1("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n");
00173         return FALSE;
00174     }
00175 
00176     /* Initialize the UNICODE_STRING and copy the driver name */
00177     RtlInitEmptyUnicodeString(&pDriverInfo->DriverName,
00178                               (PWSTR)(pDriverInfo + 1),
00179                               pstrPathName->Length);
00180     RtlCopyUnicodeString(&pDriverInfo->DriverName, pstrPathName);
00181 
00182     /* Try to load the driver */
00183     Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation,
00184                                     pDriverInfo,
00185                                     sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
00186 
00187     if (!NT_SUCCESS(Status))
00188     {
00189         DPRINT1("Failed to load a GDI driver: '%S', Status = 0x%lx\n",
00190                 pstrPathName->Buffer, Status);
00191 
00192         /* Free the allocated memory */
00193         ExFreePoolWithTag(pDriverInfo, GDITAG_LDEV);
00194         return FALSE;
00195     }
00196 
00197     /* Set the driver info */
00198     pldev->pGdiDriverInfo = pDriverInfo;
00199 
00200     /* Return success. */
00201     return TRUE;
00202 }
00203 
00204 VOID
00205 NTAPI
00206 LDEVOBJ_vUnloadImage(
00207     IN PLDEVOBJ pldev)
00208 {
00209     NTSTATUS Status;
00210 
00211     /* Make sure we have a driver info */
00212     ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
00213 
00214     /* Check if we have loaded a driver */
00215     if (pldev->pfn.DisableDriver)
00216     {
00217         /* Call the unload function */
00218         pldev->pfn.DisableDriver();
00219     }
00220 
00221     /* Unload the driver */
00222     Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
00223                                     &pldev->pGdiDriverInfo->ImageAddress,
00224                                     sizeof(HANDLE));
00225     if (!NT_SUCCESS(Status))
00226     {
00227         DPRINT1("Failed to unload the driver, this is bad.\n");
00228     }
00229 
00230     /* Free the driver info structure */
00231     ExFreePoolWithTag(pldev->pGdiDriverInfo, GDITAG_LDEV);
00232     pldev->pGdiDriverInfo = NULL;
00233 }
00234 
00235 BOOL
00236 NTAPI
00237 LDEVOBJ_bLoadDriver(
00238     IN PLDEVOBJ pldev)
00239 {
00240     PFN_DrvEnableDriver pfnEnableDriver;
00241     DRVENABLEDATA ded;
00242     ULONG i;
00243 
00244     /* Make sure we have a driver info */
00245     ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
00246 
00247     /* Call the drivers DrvEnableDriver function */
00248     RtlZeroMemory(&ded, sizeof(ded));
00249     pfnEnableDriver = pldev->pGdiDriverInfo->EntryPoint;
00250     if (!pfnEnableDriver(GDI_ENGINE_VERSION, sizeof(ded), &ded))
00251     {
00252         DPRINT1("DrvEnableDriver failed\n");
00253 
00254         /* Unload the image. */
00255         LDEVOBJ_vUnloadImage(pldev);
00256         return FALSE;
00257     }
00258 
00259     /* Copy the returned driver version */
00260     pldev->ulDriverVersion = ded.iDriverVersion;
00261 
00262     /* Fill the driver function array */
00263     for (i = 0; i < ded.c; i++)
00264     {
00265         pldev->apfn[ded.pdrvfn[i].iFunc] = ded.pdrvfn[i].pfn;
00266     }
00267 
00268     /* Return success. */
00269     return TRUE;
00270 }
00271 
00272 
00273 PVOID
00274 NTAPI
00275 LDEVOBJ_pvFindImageProcAddress(
00276     IN PLDEVOBJ pldev,
00277     IN LPSTR    pszProcName)
00278 {
00279     PVOID pvImageBase;
00280     PIMAGE_EXPORT_DIRECTORY pExportDir;
00281     PVOID pvProcAdress = NULL;
00282     PUSHORT pOrdinals;
00283     PULONG pNames, pAddresses;
00284     ULONG i;
00285 
00286     /* Make sure we have a driver info */
00287     ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
00288 
00289     /* Get the pointer to the export directory */
00290     pvImageBase = pldev->pGdiDriverInfo->ImageAddress;
00291     pExportDir = pldev->pGdiDriverInfo->ExportSectionPointer;
00292     if (!pExportDir)
00293     {
00294         return NULL;
00295     }
00296 
00297     /* Get pointers to some tables */
00298     pNames = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfNames);
00299     pOrdinals = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfNameOrdinals);
00300     pAddresses = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfFunctions);
00301 
00302     /* Loop the export table */
00303     for (i = 0; i < pExportDir->NumberOfNames; i++)
00304     {
00305         /* Compare the name */
00306         if (_stricmp(pszProcName, RVA_TO_ADDR(pvImageBase, pNames[i])) == 0)
00307         {
00308             /* Found! Calculate the procedure address */
00309             pvProcAdress = RVA_TO_ADDR(pvImageBase, pAddresses[pOrdinals[i]]);
00310             break;
00311         }
00312     }
00313 
00314     /* Return the address */
00315     return pvProcAdress;
00316 }
00317 
00318 PLDEVOBJ
00319 NTAPI
00320 EngLoadImageEx(
00321     LPWSTR pwszDriverName,
00322     ULONG ldevtype)
00323 {
00324     WCHAR acwBuffer[MAX_PATH];
00325     PLDEVOBJ pldev;
00326     UNICODE_STRING strDriverName;
00327     ULONG cwcLength;
00328     LPWSTR pwsz;
00329 
00330     DPRINT("EngLoadImageEx(%ls, %ld)\n", pwszDriverName, ldevtype);
00331     ASSERT(pwszDriverName);
00332 
00333     /* Initialize buffer for the the driver name */
00334     RtlInitEmptyUnicodeString(&strDriverName, acwBuffer, sizeof(acwBuffer));
00335 
00336     /* Start path with systemroot */
00337     RtlAppendUnicodeToString(&strDriverName, L"\\SystemRoot\\System32\\");
00338 
00339     /* Get Length of given string */
00340     cwcLength = wcslen(pwszDriverName);
00341 
00342     /* Check if we have a system32 path given */
00343     pwsz = pwszDriverName + cwcLength;
00344     while (pwsz > pwszDriverName)
00345     {
00346         if (_wcsnicmp(pwsz, L"\\system32\\", 10) == 0)
00347         {
00348             /* Driver name starts after system32 */
00349             pwsz += 10;
00350             break;
00351         }
00352         pwsz--;
00353     }
00354 
00355     /* Append the driver name */
00356     RtlAppendUnicodeToString(&strDriverName, pwsz);
00357 
00358     /* MSDN says "The driver must include this suffix in the pwszDriver string."
00359        But in fact it's optional.
00360 
00361        ms win32k EngLoadImageEx loading .sys file without append .dll
00362     */
00363     if ( (_wcsnicmp(pwszDriverName + cwcLength - 4, L".dll", 4) != 0) &&
00364          (_wcsnicmp(pwszDriverName + cwcLength - 4, L".sys", 4) != 0) )
00365     {
00366         /* Append the .dll suffix */
00367         RtlAppendUnicodeToString(&strDriverName, L".dll");
00368     }
00369 
00370     /* Lock loader */
00371     EngAcquireSemaphore(ghsemLDEVList);
00372 
00373     /* Search the List of LDEVS for the driver name */
00374     for (pldev = gpldevHead; pldev != NULL; pldev = pldev->pldevNext)
00375     {
00376         /* Check if the ldev is associated with a file */
00377         if (pldev->pGdiDriverInfo)
00378         {
00379             /* Check for match (case insensative) */
00380             if (RtlEqualUnicodeString(&pldev->pGdiDriverInfo->DriverName, &strDriverName, 1))
00381             {
00382                 /* Image found in LDEV list */
00383                 break;
00384             }
00385         }
00386     }
00387 
00388     /* Did we find one? */
00389     if (!pldev)
00390     {
00391         /* No, allocate a new LDEVOBJ */
00392         pldev = LDEVOBJ_AllocLDEV(ldevtype);
00393         if (!pldev)
00394         {
00395             DPRINT1("Could not allocate LDEV\n");
00396             goto leave;
00397         }
00398 
00399         /* Load the image */
00400         if (!LDEVOBJ_bLoadImage(pldev, &strDriverName))
00401         {
00402             LDEVOBJ_vFreeLDEV(pldev);
00403             pldev = NULL;
00404             DPRINT1("LDEVOBJ_bLoadImage failed\n");
00405             goto leave;
00406         }
00407 
00408         /* Shall we load a driver? */
00409         if (ldevtype != LDEV_IMAGE)
00410         {
00411             /* Load the driver */
00412             if (!LDEVOBJ_bLoadDriver(pldev))
00413             {
00414                 DPRINT1("LDEVOBJ_bLoadDriver failed\n");
00415                 LDEVOBJ_vFreeLDEV(pldev);
00416                 pldev = NULL;
00417                 goto leave;
00418             }
00419         }
00420 
00421         /* Insert the LDEV into the global list */
00422         pldev->pldevPrev = NULL;
00423         pldev->pldevNext = gpldevHead;
00424         gpldevHead = pldev;
00425     }
00426 
00427     /* Increase ref count */
00428     pldev->cRefs++;
00429 
00430 leave:
00431     /* Unlock loader */
00432     EngReleaseSemaphore(ghsemLDEVList);
00433 
00434     DPRINT("EngLoadImageEx returning %p\n", pldev);
00435 
00436     return pldev;
00437 }
00438 
00439 
00442 HANDLE
00443 APIENTRY
00444 EngLoadImage(
00445     LPWSTR pwszDriverName)
00446 {
00447     return (HANDLE)EngLoadImageEx(pwszDriverName, LDEV_IMAGE);
00448 }
00449 
00450 
00451 VOID
00452 APIENTRY
00453 EngUnloadImage(
00454     IN HANDLE hModule)
00455 {
00456     PLDEVOBJ pldev = (PLDEVOBJ)hModule;
00457 
00458     /* Make sure the LDEV is in the list */
00459     ASSERT(pldev->pldevPrev || pldev->pldevNext);
00460 
00461     /* Lock loader */
00462     EngAcquireSemaphore(ghsemLDEVList);
00463 
00464     /* Decrement reference count */
00465     pldev->cRefs--;
00466 
00467     /* No more references left? */
00468     if (pldev->cRefs == 0)
00469     {
00470         /* Remove ldev from the list */
00471         if (pldev->pldevPrev)
00472             pldev->pldevPrev->pldevNext = pldev->pldevNext;
00473         if (pldev->pldevNext)
00474             pldev->pldevNext->pldevPrev = pldev->pldevPrev;
00475 
00476         /* Unload the image and free the LDEV */
00477         LDEVOBJ_vUnloadImage(pldev);
00478         LDEVOBJ_vFreeLDEV(pldev);
00479     }
00480 
00481     /* Unlock loader */
00482     EngReleaseSemaphore(ghsemLDEVList);
00483 }
00484 
00485 
00486 PVOID
00487 APIENTRY
00488 EngFindImageProcAddress(
00489     IN HANDLE hModule,
00490     IN LPSTR  lpProcName)
00491 {
00492     PLDEVOBJ pldev = (PLDEVOBJ)hModule;
00493 
00494     ASSERT(gpldevWin32k != NULL);
00495 
00496     /* Check if win32k is requested */
00497     if (!pldev)
00498     {
00499         pldev = gpldevWin32k;
00500     }
00501 
00502     /* Check if the drivers entry point is requested */
00503     if (_strnicmp(lpProcName, "DrvEnableDriver", 15) == 0)
00504     {
00505         return pldev->pGdiDriverInfo->EntryPoint;
00506     }
00507 
00508     /* Try to find the address */
00509     return LDEVOBJ_pvFindImageProcAddress(pldev, lpProcName);
00510 }
00511 
00512 /* EOF */

Generated on Sat May 26 2012 04:37:08 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.