[SPOOLSS] Stub BuildOtherNamesFromMachineName as seen in wine commit cdb5f35. This...
[reactos.git] / reactos / win32ss / printing / base / spoolss / main.c
index ec01ff0..f8dfdda 100644 (file)
 
 #include "precomp.h"
 
+// Global Variables
 HANDLE hProcessHeap;
-PRINTPROVIDOR LocalSplFuncs;
+LIST_ENTRY PrintProviderList;
 
 
-BOOL WINAPI
-DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+static DWORD
+_AddPrintProviderToList(PCWSTR pwszFileName)
 {
-    switch (fdwReason)
+    DWORD dwErrorCode;
+    HINSTANCE hinstPrintProvider;
+    PInitializePrintProvidor pfnInitializePrintProvidor;
+    PSPOOLSS_PRINT_PROVIDER pPrintProvider = NULL;
+
+    // Try to load it.
+    hinstPrintProvider = LoadLibraryW(pwszFileName);
+    if (!hinstPrintProvider)
     {
-        case DLL_PROCESS_ATTACH:
-            DisableThreadLibraryCalls(hinstDLL);
-            hProcessHeap = GetProcessHeap();
-            break;
+        dwErrorCode = GetLastError();
+        ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
+        goto Cleanup;
     }
 
-    return TRUE;
+    // Get the initialization routine.
+    pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstPrintProvider, "InitializePrintProvidor");
+    if (!pfnInitializePrintProvidor)
+    {
+        dwErrorCode = GetLastError();
+        ERR("GetProcAddress failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Create a new SPOOLSS_PRINT_PROVIDER structure for it.
+    pPrintProvider = DllAllocSplMem(sizeof(SPOOLSS_PRINT_PROVIDER));
+    if (!pPrintProvider)
+    {
+        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+        ERR("DllAllocSplMem failed!\n");
+        goto Cleanup;
+    }
+
+    // Call the Print Provider initialization function.
+    if (!pfnInitializePrintProvidor(&pPrintProvider->PrintProvider, sizeof(PRINTPROVIDOR), NULL))
+    {
+        dwErrorCode = GetLastError();
+        ERR("InitializePrintProvidor failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Add this Print Provider to the list.
+    InsertTailList(&PrintProviderList, &pPrintProvider->Entry);
+
+    // Don't let the cleanup routine free this.
+    pPrintProvider = NULL;
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    if (pPrintProvider)
+        DllFreeSplMem(pPrintProvider);
+
+    return dwErrorCode;
 }
 
-BOOL WINAPI
-InitializeRouter(HANDLE SpoolerStatusHandle)
+static BOOL
+_InitializePrintProviderList()
 {
-    HINSTANCE hinstLocalSpl;
-    PInitializePrintProvidor pfnInitializePrintProvidor;
+    DWORD cbFileName;
+    DWORD cchMaxSubKey;
+    DWORD cchPrintProviderName;
+    DWORD dwErrorCode;
+    DWORD dwSubKeys;
+    DWORD i;
+    HKEY hKey = NULL;
+    HKEY hSubKey = NULL;
+    PWSTR pwszPrintProviderName = NULL;
+    WCHAR wszFileName[MAX_PATH];
 
-    // Only initialize localspl.dll for now.
-    // This function should later look for all available print providers in the registry and initialize all of them.
-    hinstLocalSpl = LoadLibraryW(L"localspl");
-    if (!hinstLocalSpl)
+    // Initialize an empty list for our Print Providers.
+    InitializeListHead(&PrintProviderList);
+
+    // First add the Local Spooler.
+    // This one must exist and must be the first one in the list.
+    dwErrorCode = _AddPrintProviderToList(L"localspl");
+    if (dwErrorCode != ERROR_SUCCESS)
     {
-        ERR("LoadLibraryW for localspl failed with error %lu!\n", GetLastError());
-        return FALSE;
+        ERR("The Local Spooler could not be loaded!\n");
+        goto Cleanup;
     }
 
-    pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstLocalSpl, "InitializePrintProvidor");
-    if (!pfnInitializePrintProvidor)
+    // Now add additional Print Providers from the registry.
+    // First of all, open the key containing print providers.
+    dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ, &hKey);
+    if (dwErrorCode != ERROR_SUCCESS)
     {
-        ERR("GetProcAddress failed with error %lu!\n", GetLastError());
-        return FALSE;
+        ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
     }
 
-    if (!pfnInitializePrintProvidor(&LocalSplFuncs, sizeof(PRINTPROVIDOR), NULL))
+    // Get the number of Print Providers and maximum sub key length.
+    dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
+    if (dwErrorCode != ERROR_SUCCESS)
     {
-        ERR("InitializePrintProvidor failed for localspl with error %lu!\n", GetLastError());
-        return FALSE;
+        ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
+        goto Cleanup;
+    }
+
+    // Allocate a temporary buffer for the Print Provider names.
+    pwszPrintProviderName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
+    if (!pwszPrintProviderName)
+    {
+        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+        ERR("DllAllocSplMem failed!\n");
+        goto Cleanup;
+    }
+
+    // Loop through all available Print Providers.
+    for (i = 0; i < dwSubKeys; i++)
+    {
+        // Cleanup tasks from the previous run
+        if (hSubKey)
+        {
+            RegCloseKey(hSubKey);
+            hSubKey = NULL;
+        }
+
+        // Get the name of this Print Provider.
+        cchPrintProviderName = cchMaxSubKey + 1;
+        dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pwszPrintProviderName, &cchPrintProviderName, NULL, NULL, NULL, NULL);
+        if (dwErrorCode != ERROR_SUCCESS)
+        {
+            ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode);
+            continue;
+        }
+
+        // Open this Print Provider's registry key.
+        dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pwszPrintProviderName, 0, KEY_READ, &hSubKey);
+        if (dwErrorCode != ERROR_SUCCESS)
+        {
+            ERR("RegOpenKeyExW failed for Print Provider \"%S\" with status %lu!\n", pwszPrintProviderName, dwErrorCode);
+            continue;
+        }
+
+        // Get the file name of the Print Provider.
+        cbFileName = MAX_PATH * sizeof(WCHAR);
+        dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName);
+        if (dwErrorCode != ERROR_SUCCESS)
+        {
+            ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
+            continue;
+        }
+
+        // Load and add it to the list.
+        dwErrorCode = _AddPrintProviderToList(wszFileName);
+        if (dwErrorCode != ERROR_SUCCESS)
+            continue;
+    }
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    // Inside the loop
+    if (hSubKey)
+        RegCloseKey(hSubKey);
+
+    // Outside the loop
+    if (pwszPrintProviderName)
+        DllFreeSplMem(pwszPrintProviderName);
+
+    if (hKey)
+        RegCloseKey(hKey);
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hinstDLL);
+                       hProcessHeap = GetProcessHeap();
+            break;
     }
 
     return TRUE;
 }
 
+BOOL WINAPI
+InitializeRouter(HANDLE SpoolerStatusHandle)
+{
+    return _InitializePrintProviderList();
+}
+
 BOOL WINAPI
 SplInitializeWinSpoolDrv(PVOID* pTable)
 {
@@ -94,9 +239,21 @@ SplIsUpgrade()
        return FALSE;
 }
 
-DWORD WINAPI
+BOOL WINAPI
 SpoolerInit()
 {
     // Nothing to do here yet
-    return ERROR_SUCCESS;
+    SetLastError(ERROR_SUCCESS);
+    return TRUE;
+}
+
+BOOL WINAPI
+BuildOtherNamesFromMachineName(LPVOID * ptr1, LPVOID * ptr2)
+{
+    FIXME("(%p, %p) stub\n", ptr1, ptr2);
+
+    *ptr1 = NULL;
+    *ptr2 = NULL;
+    return FALSE;
 }
+